我下面的查询正在工作,我发誓。。。现在,它突然dead,输出'ORA-00923 FROM keyword not found where expected
'。。我不明白为什么。。。我试过各种各样的linter和语法检查器;我只是在数组数据中迭代,并推送到oracle表/行中——如果找不到table_id
,则添加一个新条目,如果找到,则更新table_id
。我错过了什么?
数据输入也很完美。。我做错了什么。。
$fd = json_decode($df, true);
foreach ($fd as $key=>$data) {
var_dump($data);
$sql = "MERGE INTO app.table a
using (SELECT '${data[0]}' table_id,
'${data[1]}' fac_ident,
'${data[2]}' lg_name,
'${data[3]}' basic_tp,
'${data[4]}' catc_vd,
'${data[5]}' address,
'${data[6]}' assoc_city,
'${data[7]}' latitude,
'${data[8]}' longitude,
'${data[9]}' assoc_cnty,
'${data[10]}' assoc_st,
'${data[11]}' time_zone,
FROM dual) p
ON ( a.table_id = p.table_id )
WHEN matched THEN
UPDATE SET a.fac_ident = p.fac_ident,
a.lg_name = p.lg_name,
a.basic_tp = p.basic_tp,
a.catc_vd = p.catc_vd,
a.address = p.address,
a.assoc_city = p.assoc_city,
a.latitude = p.latitude,
a.longitude = p.longitude,
a.assoc_cnty = p.assoc_cnty,
a.assoc_st = p.assoc_st,
a.time_zone = p.time_zone,
WHEN NOT matched THEN
INSERT (table_id,
fac_ident,
lg_name,
basic_tp,
catc_vd,
address,
assoc_city,
latitude,
longitude,
assoc_cnty,
assoc_st,
time_zone)
VALUES (p.table_id,
p.fac_ident,
p.lg_name,
p.basic_tp,
p.catc_vd,
p.address,
p.assoc_city,
p.latitude,
p.longitude,
p.assoc_cnty,
p.assoc_st,
p.time_zone)";
..........
如果您的数据包含一个引号,则相当于试图执行SQL注入攻击。
不使用变量解析${data[0]}
;相反,使用绑定变量创建查询并正确传递数据,这样就不会受到SQL注入攻击。
例如:
如果你有表格:
CREATE TABLE table_name (
table_id VARCHAR2(100),
fac_ident VARCHAR2(100)
)
如果你有1
的table_id
和2
的fac_ident
,那么你的合并将是:
MERGE INTO table_name a
USING (
SELECT '1' table_id,
'2' fac_ident
FROM dual
) p
ON ( a.table_id = p.table_id )
WHEN matched THEN
UPDATE SET a.fac_ident = p.fac_ident
WHEN NOT matched THEN
INSERT (table_id, fac_ident )
VALUES (p.table_id, p.fac_ident );
这是有效的。
但是,如果fac_ident
的值为This value has a 'quote' inside it.
,则您的查询为:
MERGE INTO table_name a
USING (
SELECT '1' table_id,
'This value has a 'quote' inside it.' fac_ident
FROM dual
) p
ON ( a.table_id = p.table_id )
WHEN matched THEN
UPDATE SET a.fac_ident = p.fac_ident
WHEN NOT matched THEN
INSERT (table_id, fac_ident )
VALUES (p.table_id, p.fac_ident );
并失败:
ORA-00923: FROM keyword not found where expected
更隐蔽的是,如果fac_indent
的值为'||(SELECT secret_column FROM secret_data WHERE ROWNUM = 1)||'
,则您的查询变为:
MERGE INTO table_name a
USING (
SELECT '1' table_id,
''||(SELECT secret_column FROM secret_data WHERE ROWNUM = 1)||'' fac_ident
FROM dual
) p
ON ( a.table_id = p.table_id )
WHEN matched THEN
UPDATE SET a.fac_ident = p.fac_ident
WHEN NOT matched THEN
INSERT (table_id, fac_ident )
VALUES (p.table_id, p.fac_ident );
而且,如果表SECRET_DATA
存在并且具有列SECRET_COLUMN
,那么您的查询不会失败,并且用户可以开始对您的查询执行意外的操作。请不要让他们这样做,并使用最佳实践,即使用绑定变量而不是字符串串联来制定查询。
db<gt;小提琴这里