我想构建一个 PHP 脚本来验证 SQL 查询,但不执行它。它不仅应该验证语法,而且如果可能的话,应该让您知道在给定查询中的命令的情况下是否可以执行查询。这是我希望它做什么的伪代码:
<?php
//connect user
//connect to database
//v_query = $_GET['usrinput'];
if(validate v_query == true){
echo "This query can be executed";
}
else{
echo "This query can't be executed because the table does not exist.";
}
//disconnect
?>
类似这样的事情。我希望它模拟查询而不执行它。这就是我想要的,但我找不到任何相关信息。
我们不希望执行查询的一个例子是,如果查询向数据库添加了某些内容。我们只是想让它模拟它而不修改数据库。
任何链接或示例将不胜感激!
从 MySQL 5.6.3 开始,您可以对大多数查询使用 EXPLAIN
我做了这个,效果很好:
function checkMySqlSyntax($mysqli, $query) {
if ( trim($query) ) {
// Replace characters within string literals that may *** up the process
$query = replaceCharacterWithinQuotes($query, '#', '%') ;
$query = replaceCharacterWithinQuotes($query, ';', ':') ;
// Prepare the query to make a valid EXPLAIN query
// Remove comments # comment ; or # comment newline
// Remove SET @var=val;
// Remove empty statements
// Remove last ;
// Put EXPLAIN in front of every MySQL statement (separated by ;)
$query = "EXPLAIN " .
preg_replace(Array("/#[^\n\r;]*([\n\r;]|$)/",
"/[Ss][Ee][Tt]\s+\@[A-Za-z0-9_]+\s*:?=\s*[^;]+(;|$)/",
"/;\s*;/",
"/;\s*$/",
"/;/"),
Array("","", ";","", "; EXPLAIN "), $query) ;
foreach(explode(';', $query) as $q) {
$result = $mysqli->query($q) ;
$err = !$result ? $mysqli->error : false ;
if ( ! is_object($result) && ! $err ) $err = "Unknown SQL error";
if ( $err) return $err ;
}
return false ;
}
}
function replaceCharacterWithinQuotes($str, $char, $repl) {
if ( strpos( $str, $char ) === false ) return $str ;
$placeholder = chr(7) ;
$inSingleQuote = false ;
$inDoubleQuotes = false ;
$inBackQuotes = false ;
for ( $p = 0 ; $p < strlen($str) ; $p++ ) {
switch ( $str[$p] ) {
case "'": if ( ! $inDoubleQuotes && ! $inBackquotes ) $inSingleQuote = ! $inSingleQuote ; break ;
case '"': if ( ! $inSingleQuote && ! $inBackquotes ) $inDoubleQuotes = ! $inDoubleQuotes ; break ;
case '`': if ( ! $inSingleQuote && ! $inDoubleQuotes ) $inBackquotes = ! $inBackquotes ; break ;
case '\\': $p++ ; break ;
case $char: if ( $inSingleQuote || $inDoubleQuotes || $inBackQuotes) $str[$p] = $placeholder ; break ;
}
}
return str_replace($placeholder, $repl, $str) ;
}
如果查询成功(允许多个;分隔的语句),它将返回 False,或者如果存在语法或其他 MySQL 其他(例如不存在的表或列),则会返回一条错误消息,说明错误。
已知错误:
您可以尝试这个库:http://code.google.com/p/php-sql-parser/。我还没有使用过它,所以我不能保证它,但代码看起来能够区分有效和无效 SQL 之间的区别。
如果您的 SQL 变体允许,另一种选择可能是使用事务。事务允许您执行 SQL,然后取消它,以逆转所造成的任何损坏。不过我想我更喜欢选项 1。
您不能只解析和验证 SQL,因为您需要检查表是否存在、JOIN 的有效性等。进行完整集成测试的唯一方法是实际运行查询。您可以将其包装在事务中,然后回滚。然而,设计不当或恶意的查询仍然可能导致您的服务器瘫痪或破坏数据。
对我来说: 我创建了一个没有权限的用户
GRANT USAGE ON *.* TO `command_user`@`localhost
我在这个用户上执行mysql命令。
并使用
try-catch
块 -> if 语法错误 => false
, else => true