需要在使用TCL

时间:2016-11-10 07:52:41

标签: sql tcl

我有一个存储在变量中的SQL语句:

我使用文件操作

从“.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是动态生成的。

所以我需要先存储没有WHERE id = 1617075子句的 sql ,然后在'statement'变量中加入where子句。

基本上在语句中添加一些名为$id的数据。

2 个答案:

答案 0 :(得分: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,这将成为

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

答案 1 :(得分: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 ,但我认为在这种情况下字符串映射可能更有用。