clq

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

pdo 参数绑定中 where 子句中的错误的解决

select * from  admin where 1=1  and admin_name =  '$user_name'

象这句是会出错的,说 rang 什么的参数个数不正确之类的. 我也想过是否是 ' 引号造成的,但在 insert 里是这样的呀. 最后解决是目前的 php5.2 的 pdo 中操作 qlite3 要对 where 子句上的特殊处理,即 where 子句中是不要加 ' 引号.

select * from  admin where 1=1  and admin_name =  $user_name

这样就 ok 了

--------------------------------------------------

http://hi.baidu.com/ichuan/blog/item/0002da228dd1965e9822edbe.html

PDO的参数绑定与postgresql数组类型列的冲突
2010-03-17 16:16
php中可以使用PDO来进行数据库操作,利用PDO提供的参数绑定( PDOStatement::bind*系列函数 ),将SQL语句中的条件部分绑定到php变量上,可以基本防止SQL注入攻击。下边是php.net上的一个例子:

 1  <?php
 2  
/* Execute a prepared statement by binding PHP variables */
 3  
$calories 150;
 4  
$colour 'red';
 5  
$sth $dbh->prepare('SELECT name, colour, calories
 6      FROM fruit
 7      WHERE calories < :calories AND colour = :colour'
);
 8  
$sth->bindValue(':calories'$caloriesPDO::PARAM_INT);
 9  
$sth->bindValue(':colour'$colourPDO::PARAM_STR);
10  
$sth->execute();
11  
?>


PDO中使用的是“冒号”作为占位符,如果你的SQL语句中本身有冒号,PDO就会理解为待绑定参数,查询的时候就会有问题。今天在使用PDO时出现了错误,下边是代码:

1  <?php
2  $dbo 
= new PDO("pgsql:dbname=x""u""p");
3  
$stmt $dbo->prepare('SELECT id, arr[1:4] FROM table1 WHERE id in (3397,3398,3399,3401) limit 10');
4  
$stmt->execute();
5  
var_dump($stmt->fetchAll());
6  
var_dump($stmt->errorInfo());
7  
?>


数据库使用的是postgresql,其中arr是类型为数组的列,我这句是想取出arr数组列的前4个元素,然后输出有错误:

 1  array(0) {
 2  }
 3  array(3) {
 4    [0]=>
 5    string(5) "00000"
 6    [1]=>
 7    int(7)
 8    [2]=>
 9    string(52) "ERROR:  syntax error at or near "$1" at character 72"
10  }


原因就是PDO把 ':4' 理解为了占位符,报出此占位符语法错误(标识符不能以数字开头)。
然后 google 了半天没解决办法,后来在冒号后边加了个空格解决了:

3  $stmt $dbo->prepare('SELECT id, arr[1: 4] FROM table1 WHERE ...

加个空格躲过了PDO的检查,而postgresql依然能正确识别 'arr[1: 4]'  为 'arr[1:4]',所以查询正确了。
--------------------------------------------------
http://dev-bbs.com/t6131303.html
Dev BBS -> 数据库 -> sqlite中这样绑定参数行不行的? - VC/MFC / 数据库 [打印本页]  
san_77227487 2010-06-24 13:19
 
sql = "update qin_country set values1 = ?1 where group_name = ?2; update qin_country set values2 = ?3 where group_name = ?2; "; (两个语句,用分号隔开)

.........

int error1,error2,error3;
error1 = sqlite3_bind_text(m_stmt, 1, buff1, strlen(buff1), NULL);
error2 = sqlite3_bind_text(m_stmt, 2, buff2, strlen(buff2), NULL);
error3 = sqlite3_bind_text(m_stmt, 3, buff3, strlen(buff3), NULL);

......


如上的代码,error1和error2都返回正确,但error3返回失败.
我估计是因为第三个参数,是在sql语句中的第二句,但绑定参数只能绑定在第一句的范围.

那请问下,我这个问题可以解决吗? 我想同时绑定参数和运行这个由两个语句组成的sql语句

stonewater 2010-06-24 13:24
获取下错误信息看看是什么错误


san_77227487 2010-06-24 13:32
引用 1 楼 stonewater 的回复:
获取下错误信息看看是什么错误

赞助商链接 2010-06-24 13:32
 

san_77227487 2010-06-24 13:35
另外,虽然这两条语句是可以合并成一条语句. 但这只是一个测试例子, 我想做的是可以同时运行多条语句的功能

licry01 2010-06-24 13:51
试试不用"?" 方式的绑定, 比如

sql = "update qin_country set values1 = @values1 where group_name = @values2; update qin_country set values2 = @values3 where group_name = @values2; ";

第一步:
index = sqlite3_bind_parameter_index(m_stmt, "@values1"); 
第二步:
error1 = sqlite3_bind_text(m_stmt, index, buff1, strlen(buff1), NULL);

 

san_77227487 2010-06-24 14:02
引用 4 楼 licry01 的回复:
试试不用"?" 方式的绑定, 比如

sql = "update qin_country set values1 = @values1 where group_name = @values2; update qin_country set values2 = @values3 where group_name = @values2; ";

第一步:
index = sqlite3_bi……

licry01 2010-06-24 15:38
我试了下,是可以的啊
你是不是绑定参数前忘记了调用sqlite3_prepare(.......................) ?????
要不你用的就是sqlite3_exec

我是下面这样的逻辑:
1.sqlite3_prepare
2.绑定各种参数
3.sqlite3_step
4.sqlite3_finalize

san_77227487 2010-06-24 15:57
引用 6 楼 licry01 的回复:
我试了下,是可以的啊
你是不是绑定参数前忘记了调用sqlite3_prepare(.......................) ?????
要不你用的就是sqlite3_exec

我是下面这样的逻辑:
1.sqlite3_prepare
2.绑定各种参数
3.sqlite3_step
4.sqlite3_finalize

licry01 2010-06-24 16:18
引用 5 楼 san_77227487 的回复:
在执行第三个参数的 index3 = sqlite3_bind_parameter_index(m_stmt, "@values3"); 时,返回给index的值是0, 0是错误的,应该是3

所以这种方法应该也是不行

san_77227487 2010-06-24 16:22
引用 8 楼 licry01 的回复:
引用 5 楼 san_77227487 的回复:
在执行第三个参数的 index3 = sqlite3_bind_parameter_index(m_stmt, "@values3"); 时,返回给index的值是0, 0是错误的,应该是3

所以这种方法应该也是不行


我觉得是你第3个参数绑定有问题, 我这绑一大堆都没有问题
你把跟第3个绑定操作相关的代码贴上来看看

san_77227487 2010-06-24 16:25
以下是我的代码,不行

C/C++ code



#include
"stdafx.h"
#include
"sqlite3.h"
#include
<windows.h>

void my_test()
{
system(
"del db1.sqlite3");

int ret;
sqlite3
*pdb =0;
sqlite3_stmt
*stmt =0;
char*error =0;
constchar*tail =0;

int index1, index2, index3;
constvoid*value ="asdfadsfasdfjasdfjaksdfaskjdfakdsfaksfja";

ret
= sqlite3_open("db1.sdb", &pdb); //打开数据库,跟打开文本文件一样
if( ret != SQLITE_OK )
return;

ret
= sqlite3_exec(pdb, "CREATE TABLE qin_country (GROUP_NAME BLOB PRIMARY KEY, VALUES1 BLOB, VALUES2 BLOB);", 0,0, &error );
if( ret != SQLITE_OK )
return;

ret
= sqlite3_exec(pdb, "insert into qin_country values(\'group_1234\',\'55555\',\'xxxxy\');", 0,0, &error );
if( ret != SQLITE_OK )
return;

char*sql ="update qin_country set values1 = @pa1 where group_name = @pa2; \
update qin_country set values2 = @pa3 where group_name = @pa2; ";

ret
= sqlite3_prepare(pdb, sql,strlen(sql), &stmt, &tail);
if( ret != SQLITE_OK )
return;

index1
= sqlite3_bind_parameter_index(stmt, "@pa1");
index2
= sqlite3_bind_parameter_index(stmt, "@pa2");
index3
= sqlite3_bind_parameter_index(stmt, "@pa3");

ret
= sqlite3_bind_blob(stmt, index1, value, strlen((char*)value), SQLITE_STATIC);
ret
= sqlite3_bind_blob(stmt, index2, value, strlen((char*)value), SQLITE_STATIC);
ret
= sqlite3_bind_blob(stmt, index3, value, strlen((char*)value), SQLITE_STATIC);

if( ret != SQLITE_OK )
return;

ret
= sqlite3_step(stmt);
if( ret != SQLITE_DONE )
return;

sqlite3_close(pdb);
}


licry01 2010-06-24 16:27
我的sql是下面这样的:
INSERT INTO [objects](project_id, display_name,parent_id,operator,sequence_num)  
VALUES(@project_id, @node_name, @pid, @p_uid, (select (ifnull(max(sequence_num),1)+1) from [objects] where parent_id=@pid)) ;
insert into [objects_properties](object_id, prop_id) 
select (select object_id from [objects] where parent_id=@pid and display_name=@node_name and project_id=@project_id), prop_id from [properties] ;


我先看看你的代码吧

san_77227487 2010-06-24 16:28
其中
system("del db1.sqlite3");
和sqlite3_open("db1.sdb", &pdb);
这里没写对应,不过没关系,不管这个

san_77227487 2010-06-24 16:30
问题就在下面这一句

index3 = sqlite3_bind_parameter_index(stmt, "@pa3");


只要 index3 = 3 就对了
但现在返回的是0

licry01 2010-06-24 16:55
呵呵, 不好意思啊, 还真如你说的, 参数在第二个子句中才出现就不行了, 只能出现在第一个子句中!
不错不错, 学习了, 看来以后我还真得要注意这地方的应用了.
我改成下面的就能运行了:
C/C++ code


void my_test()
{
system(
"del db1.sdb");

int ret;
sqlite3
*pdb =0;
sqlite3_stmt
*stmt =0;
char*error =0;
constchar*tail =0;

int index1, index2, index3;
constvoid*value ="asdfadsfasdfjasdfjaksdfaskjdfakdsfaksfja";

ret
= sqlite3_open("db1.sdb", &pdb); //打开数据库,跟打开文本文件一样
if( ret != SQLITE_OK )
return;

ret
= sqlite3_exec(pdb, "CREATE TABLE qin_country (GROUP_NAME BLOB PRIMARY KEY, VALUES1 BLOB, VALUES2 BLOB);", 0,0, &error );
if( ret != SQLITE_OK )
return;

ret
= sqlite3_exec(pdb, "insert into qin_country values(\'group_1234\',\'55555\',\'xxxxy\');", 0,0, &error );
if( ret != SQLITE_OK )
return;

char*sql ="select @pa1, @pa2, @pa3 where 0>1; update qin_country set values1 = @pa1 where group_name = @pa2; update qin_country set values2 = @pa3 where group_name = @pa2; ";
//char *sql = "update qin_country set values1 = @pa1 where group_name = @pa2; update qin_country set values2 = @pa3 where group_name = @pa2; ";
//char *sql = "update qin_country set values1 = @pa1, values2=@pa3 where group_name = @pa2; ";

ret
= sqlite3_prepare(pdb, sql,strlen(sql), &stmt, &tail);
if( ret != SQLITE_OK )
return;

index1
= sqlite3_bind_parameter_index(stmt, "@pa1");
ret
= sqlite3_bind_blob(stmt, index1, value, strlen((char*)value), SQLITE_STATIC);
index2
= sqlite3_bind_parameter_index(stmt, "@pa2");
ret
= sqlite3_bind_blob(stmt, index2, value, strlen((char*)value), SQLITE_STATIC);
index3
= sqlite3_bind_parameter_index(stmt, "@pa3");
ret
= sqlite3_bind_blob(stmt, index3, value, strlen((char*)value), SQLITE_STATIC);

if( ret != SQLITE_OK )
return;

ret
= sqlite3_step(stmt);
if( ret != SQLITE_DONE )
return;

sqlite3_close(pdb);
}

san_77227487 2010-06-24 17:34
非常感谢!!我试试看先

san_77227487 2010-07-09 21:25
不好意思 由于临时被交付一件很赶的任务 所以没时间继续测试这个问题

licry01的方法我试过了,的确可以绑定,但sqlite3_step时有错啊,数据库里的数据没有被update

还是不行,原因未知
posted on 2012-02-04 21:46  clq  阅读(842)  评论(0编辑  收藏  举报