2016-11-10 63 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_。 –