2016-11-10 34 views
0

我有一个存储变量中SQL语句中的SQL语句之间添加字符串:需要使用TCL

我使用的文件操作得到这个“声明”,从“.SQL”文件

set statement "SELECT build_package, 
replace(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(substring(build_package, length(build_package) - position('/' in reverse(build_package)) + 2), '-BSD',''),'-LNX',''),'-esxi',''),'.repo',''),'.vmdk',''),'.qcow2',''),'.rpm',''),'.tbz',''),'-version',''),'.el7.x86_64','') ,'-NR',''),'-kvm',''),'-x86_64',''),'ptsvpl','svpts'),'spbvpl','svspb'),'sdevpl','svsde'),'-amd64',''),'.noarch',''),'.el6',''),'.x86_64',''),'tsevpl','svtse') 
FROM scheduler_jobs WHERE id = '1617075' order by id DESC" 

这里where子句是例如:WHERE id = 1617075这个id是动态生成的。

所以我需要先存储sql没有WHERE id = 1617075子句,并在以后添加where子句,当我在'语句'变量中获取它。

基本上在声明添加一些数据称为$id

回答

0

只是使用字符串映射

首先你的字符串保存为在其标签模板,并删除要替换任何部分:

set statement "SELECT build_package, 
replace(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(substring(build_package, length(build_package) - position('/' in reverse(build_package)) + 2), '-BSD',''),'-LNX',''),'-esxi',''),'.repo',''),'.vmdk',''),'.qcow2',''),'.rpm',''),'.tbz',''),'-version',''),'.el7.x86_64','') ,'-NR',''),'-kvm',''),'-x86_64',''),'ptsvpl','svpts'),'spbvpl','svspb'),'sdevpl','svsde'),'-amd64',''),'.noarch',''),'.el6',''),'.x86_64',''),'tsevpl','svtse') 
FROM scheduler_jobs <WHERE_CLAUSE> order by id DESC" 

这里我选择的标签是,但是你可以使用你喜欢的东西。

然后:

set query_cmd [string map {<WHERE_CLAUSE> "WHERE id = '123456'"} $statement] 

puts $query_cmd 

可以这样做,你需要改变字符串的许多不同的部分,只是用另一种标签。

set query_cmd [string map {<TAG1> $v1 <TAG2> $v2...} $statement] 

你当然也可以将字符串内引用变量,如:

...WHERE id = '\$id'... 

然后用SUBST,但我认为在这种情况下字符串映射可能更有用。

2

使用带有绑定变量的prepared statement

从文档的例子:

set statement [db prepare { 
    select phone_num from directory 
    where first_name = :firstname and last_name = :lastname 
}] 
set firstname Fred 
set lastname Flintstone 

作为文档解释,

针对连接的制备对象命令接受要被针对数据库执行任意SQL代码。 SQL代码可能包含绑定变量,它们是以字母数字字符或下划线字符串(该字符串的第一个字符可能不是数字),以冒号()作为前缀。如果绑定变量出现在SQL语句中,并且不在由单引号或双引号引起的字符串中,也不在由-引入的注释中,则该语句在执行语句时会变为替换值。绑定变量在结果语句中变成单个值(字符串或数字)。
驱动程序负责确保绑定变量的机制阻止SQL注入。

换句话说,虽然司机的责任,你应该对SQL注入保护。换句话说,如果id不是简单的1617075而是1617075; DROP TABLE scheduler_jobs;--,你应该仍然没问题,因为驱动程序已经正确地逃脱了这一点(而不是你必须这样做,错过了一个让你容易受到攻击的边缘案例)。


对于你的榜样,留下了所有的REPLACE S,这将成为

set statement [db prepare { 
    SELECT build_package 
    FROM scheduler_jobs 
    WHERE id = :scheduler_job_id 
    ORDER BY id DESC 
}] 
set scheduler_job_id 1617075 
+0

这是唯一的答案_correct_。 –