简体   繁体   English

SQL 的 UPDATE 请求在从 PHP 查询时失败,但在 SQL 命令行上运行良好

[英]UPDATE request for SQL fails on querying from PHP but works good on SQL command line

I am developing a page for stock maintenance.我正在开发一个用于库存维护的页面。 I am encountering a bizarre issue.我遇到了一个奇怪的问题。 When I run the PHP through AJAX everything works fine except for the mysqli_query part.当我通过 AJAX 运行 PHP 时,除了 mysqli_query 部分外,一切正常。

<?php
include 'dbconnector.php';
$item_code  =   json_decode(filter_input(INPUT_POST,'icode')) or die('line1');
$item_count =   json_decode(filter_input(INPUT_POST,'icount')) or die('line2');

$sql_string =   '';

for($i=0; $i<sizeOf($item_code); $i++)
{
    $sql_string.=" UPDATE stock_main SET iSTOK=".$item_count[$i]." WHERE iCODE=\"".$item_code[$i]."\"; ";
}

    echo $sql_string;
$query_sql  =   mysqli_query($dbconnector,$sql_string);
if($query_sql>0)
    echo 'SUCCESS';
else
    echo mysqli_error($query_sql); 
?>

The issue is when I run for a single statement it works fine.问题是当我运行单个语句时它工作正常。 When multiple statements are concatenated it returns false.当多个语句连接在一起时,它返回 false。 But the multiple statement scenario works fine in phpMyAdmin command-line.但是多语句方案在 phpMyAdmin 命令行中工作正常。 When tried to check why it fails mysqli_error returns saying the argument should be of mysqli type but it was boolean.当试图检查它为什么失败时 mysqli_error 返回说参数应该是 mysqli 类型但它是布尔值。

Warning: You are wide open to SQL Injections and should use parameterized prepared statements instead of manually building your queries.警告:您对SQL 注入持开放 态度,应该使用参数化的准备好的语句,而不是手动构建查询。 They are provided by PDO or by MySQLi .它们由PDOMySQLi 提供 Never trust any kind of input!永远不要相信任何类型的输入! Even when your queries are executed only by trusted users, you are still in risk of corrupting your data .即使您的查询仅由受信任的用户执行,您仍然存在损坏数据的风险 Escaping is not enough!逃避还不够!

Do not use mysqli_multi_query() as suggested by other answers as it only makes you more vulnerable to SQL injection.不要按照其他答案的建议使用mysqli_multi_query() ,因为它只会让您更容易受到 SQL 注入的影响。 You really do not need this function!你真的不需要这个功能! Use prepared statements, which are not only easier and safer, but also less error prone.使用准备好的语句,这不仅更容易、更安全,而且不容易出错。

// Switch error reporting!
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
include 'dbconnector.php';
$item_code = json_decode(filter_input(INPUT_POST, 'icode')) or die('line1');
$item_count = json_decode(filter_input(INPUT_POST, 'icount')) or die('line2');

// Prepare query
$stmt = $dbconnector->prepare('UPDATE stock_main SET iSTOK=? WHERE iCODE=?');

// bind and execute multiple times
for ($i = 0; $i < sizeof($item_code); $i++) {
    $stmt->bind_param('ss', $item_count[$i], $item_code[$i]);
    $stmt->execute();
}

mysqli_query function does not support multiple sql query at one time. mysqli_query 函数不支持同时进行多个 sql 查询。 It's recommended to use mysqli_multi_query() function;推荐使用mysqli_multi_query()函数;

Your line of code will be like this:-您的代码行将是这样的:-

$query_sql = mysqli_multi_query($dbconnector, $sql_string); $query_sql = mysqli_multi_query($dbconnector, $sql_string);

In order to use multiple queries, you can use为了使用多个查询,您可以使用

mysqli_multi_query ( mysqli $link , string $query )

From the PHP manual:从 PHP 手册:

The API functions mysqli_query() and mysqli_real_query() do not set a connection flag necessary for activating multi queries in the server. API 函数 mysqli_query() 和 mysqli_real_query() 不会设置激活服务器中的多查询所需的连接标志。 An extra API call is used for multiple statements to reduce the likeliness of accidental SQL injection attacks.对多条语句使用额外的 API 调用,以减少意外 SQL 注入攻击的可能性。 An attacker may try to add statements such as ;攻击者可能会尝试添加诸如 ; DROP DATABASE mysql or ;删除数据库 mysql 或 ; SELECT SLEEP(999).选择睡眠(999)。 If the attacker succeeds in adding SQL to the statement string but mysqli_multi_query is not used, the server will not execute the second, injected and malicious SQL statement.如果攻击者成功将 SQL 添加到语句字符串中,但未使用 mysqli_multi_query,则服务器将不会执行第二条注入的恶意 SQL 语句。

So your code should be:所以你的代码应该是:

<?php
include 'dbconnector.php';
$item_code  =   json_decode(filter_input(INPUT_POST,'icode')) or die('line1');
$item_count =   json_decode(filter_input(INPUT_POST,'icount')) or die('line2');

$sql_string =   '';

for($i=0; $i<sizeOf($item_code); $i++)
{
    $sql_string.=" UPDATE stock_main SET iSTOK=".$item_count[$i]." WHERE iCODE=\"".$item_code[$i]."\"; ";
}

    echo $sql_string;
$query_sql  =   mysqli_multi_query($dbconnector, $sql_string);
if($query_sql>0)
    echo 'SUCCESS';
else
    echo mysqli_error($query_sql); 
?>

Check more on Php.net Multiple StatementsPhp.net Multiple Statements上查看更多信息

For clarification为了澄清

As others suggested, it is better to use prepared statements from a SQL Injection Attack perspective, as the data will be automatically formatted and filtered.正如其他人所建议的,从 SQL 注入攻击的角度来看,最好使用准备好的语句,因为数据将被自动格式化和过滤。 However, this doesn't mean that normal queries are completely bad, as long as you take all the necessary steps to ensure you are protected.然而,这并不意味着普通查询完全不好,只要您采取所有必要的步骤来确保您受到保护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM