从dual合并为USING(在预期位置找不到ORA-00923 from关键字)



我下面的查询正在工作,我发誓。。。现在,它突然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)
)

如果你有1table_id2fac_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;小提琴这里

最新更新