使用单个mysql_query()调用执行多个查询的PHP代码

7
我正在尝试从我的PHP类中执行下面的SQL代码,但执行时出现错误。以下代码在PHPMyAdmin控制台中完美运行,但在PHP中却不能正常运行。
SET @columns := (
  SELECT
    GROUP_CONCAT(column_name)
    FROM information_schema.columns
    WHERE table_schema = 'test'
    AND table_name = 'mytable'
    AND column_key <> 'PRI'
);

SET @sql := (
  SELECT CONCAT(
    'INSERT INTO mytable (', @columns, ') ',
    'SELECT ', @columns, ' FROM mytable ',
    'WHERE id = 1;'
  )
);

PREPARE stmt FROM @sql;

EXECUTE stmt;

以下是我在PHP中的实现方法:

$sql='';
$sql.="SET @columns := (
  SELECT
    GROUP_CONCAT(column_name)
    FROM information_schema.columns
    WHERE table_schema = 'test'
    AND table_name = 'mytable'
    AND column_key <> 'PRI'
    );";

$sql.="SET @sql := (
  SELECT CONCAT(
    'INSERT INTO mytable (', @columns, ') ',
    'SELECT ', @columns, ' FROM mytable ',
    'WHERE id = 1;'
  )
);";


$sql.="PREPARE stmt FROM @sql;

        EXECUTE stmt;";

$result = mysql_query($sql, $this->connection);

我做错了什么?

看到我得到的错误:

Database query failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SET @sql := (
                              SELECT CONCAT(
                                'INSERT INTO mytable(', @colu' at line 9 

2
据我所知,已弃用的旧版mysql_...扩展不支持多语句执行。您必须逐个运行它们。 - Álvaro González
你为什么不使用PDO - Bojangles
2
每当你说“它给我一个错误”时,你也应该提供你看到的确切错误消息。如果可能的话,还要提供代码中抛出错误的位置。 - Marcello Romani
或许值得尝试检查文件的编码方式。尝试使用无BOM的UTF8编码。 - OptimusCrime
将65536作为mysql_connect的第5个参数传递。检查源代码: https://dev59.com/DWYr5IYBdhLWcg3wDWNm - Bakly
显示剩余4条评论
5个回答

7

来自手册

mysql_query()向与指定的link_identifier关联的当前活动数据库的服务器发送一个唯一的查询(不支持多个查询).

转移到mysqli,它支持多个语句


谢谢,伙计!你给了更好的答案。我发现使用PDO比迁移到mysqli更简单。你的意见是什么?期待你的评论! - tradebel123
任何一种都比你现在的好。我略微倾向于使用mysqli,因为它是PHP自带的。 - Burhan Khalid

2
/* 
Author: Jack Mason 
website:  volunteer @http://www.osipage.com , web access application and bookmarking tool. 
Language: PHP, Mysql 
This script is free and can  be used anywhere, no attribution required. 
*/ 

ini_set('display_errors', 0); 
error_reporting(0); 
// SET MYSQL CONFIGURATION 
$serverName = 'localhost'; 
$username   = 'root'; 
$password   = ''; 
$database   = 'test_delete'; 

// SET THE SQL FILE PATH OR DIRECTLY GIVE ALL SQL STATEMENTS INSIDE QUOTES 
$query = file_get_contents('file.sql'); 

//OR  to execute multiple SQL statements directly, set "$query" variable as follows: 

$query = 'CREATE TABLE IF NOT EXISTS `employee_attendances` ( 
  `id` int(11) NOT NULL AUTO_INCREMENT, 
  `attendance_date` date DEFAULT NULL, 
  `employee_id` int(11) DEFAULT NULL, 
  `employee_leave_type_id` int(11) DEFAULT NULL, 
  `reason` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
  `is_half_day` tinyint(1) DEFAULT NULL, 
  PRIMARY KEY (`id`) 
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; 
CREATE TABLE IF NOT EXISTS `items_product` ( 
  `id` int(11) NOT NULL AUTO_INCREMENT, 
  `product_name` TEXT DEFAULT NULL, 
  `price` DOUBLE DEFAULT NULL, 
  PRIMARY KEY (`id`) 
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; 
'; 


// Establishing connection with mysqli database 
$con = new mysqli($serverName, $username, $password, $database); 
/* check connection */ 
if(mysqli_connect_errno()) { 
    printf("Connect failed: %s\n", mysqli_connect_error()); 
    exit(); 
} 

/* execute multi query */ 
if($con->multi_query($query))  
{ 
    do { 
        /* store first result set */ 
        if($resultSet = $con->store_result())  
        { 
            while($row = $resultSet->fetch_row())  
            { 
                printf("%s\n", $row[0]); 
            } 
            $resultSet->free(); 
        } 

         //print divider 
        if($con->more_results())  
        { 
     $loadArray = array("Creating tables....", "please wait..", "stay tuned while all table definitions are dumped..."); 
     $upperLimit = count($loadArray) - 1; 
           $randNumb = rand(0, $upperLimit); 
           echo $loadArray[$randNumb]; echo '<br/>'; 
           $loadArray = array();  
        } 
    } while ($con->next_result()); 

    echo 'All tables have been successfully copied/created to given database!'; 
/* close connection */ 
} 
$con->close();

这段代码可以同时处理.SQL文件或直接执行多个SQL查询。经过测试,成功地一次执行了多达200张表的查询。代码摘自phpsnips页面

1

只需对MySQL数据库运行查询"set names 'utf8'",您的输出就应该正确显示。


0
请使用以下代码作为示例:
$sql.= <<<EOF
   SET @sql := (
  SELECT CONCAT(
    'INSERT INTO mytable (', @columns, ') ',
    'SELECT ', @columns, ' FROM mytable ',
    'WHERE id = 1;'
  )
)
EOF;

编辑:

$sql.= <<<EOF
  SET @columns := (
   SELECT
    GROUP_CONCAT(column_name)
    FROM information_schema.columns
    WHERE table_schema = 'test'
    AND table_name = 'mytable'
    AND column_key <> 'PRI'
    );
EOF;

使用EOF来实现这样的语句。


@tradebel123 我明白了,我已经编辑了答案。现在也要更改编辑后的语句,然后再检查一下。 - Code Lღver
我得到了相同的结果...语句在@colu附近中断了...?? - tradebel123

0
正如Burhan所指出的,mysql+php不再支持多个查询。原因可能是SQL注入。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接