Tokene未知使用动态表名创建存储过程

时间:2015-05-12 16:24:30

标签: stored-procedures firebird firebird2.5 flamerobin

我在插入表格之前尝试检查记录是否存在。

SET TERM ^ ;

CREATE PROCEDURE add_videorecord(tab_name varchar(31), col_name varchar(31),
col_value varchar(100))
RETURNS (status int)
 AS
BEGIN
status=1;
if (not exists(
select * from :tab_name where :col_name = :col_value))
then
execute statement 'insert into "'||:tab_name||'" ("'||:col_name||'") values("'||:col_value||'")';
else
status=0;
END^

SET TERM ; ^

并获得FlameRobin错误:

Message: isc_dsql_prepare failed

SQL Message : -104
Invalid token

Engine Code    : 335544569
Engine Message :
Dynamic SQL Error
SQL error code = -104
Token unknown - line 10, column 15
:

为什么它是未知的令牌?我尝试使用输入参数。

1 个答案:

答案 0 :(得分:2)

您无法像在select中那样直接参数化对象名称(如表名,列名等)。参数只能用于值。

如果要参数化对象名称,则需要将其连接到查询字符串中,就像您已经为insert语句所做的那样。您只需要注意SQL注入(例如,通过根据已知的一组已接受的对象名称检查名称)。

作为示例(不检查有效的表和列名称!):

CREATE PROCEDURE ADD_RECORD (
    TAB_NAME VARCHAR(31),
    COL_NAME VARCHAR(31),
    COL_VALUE VARCHAR(100) )
RETURNS (
    STATUS INTEGER )
AS
DECLARE temp INTEGER;
BEGIN
    status=1;
    execute statement 
      ('select 1 from "' || tab_name || '" where "' || col_name || '" = ?') (:col_value) 
      into :temp;
    if (temp is null)
    then
        execute statement 
          ('insert into "'|| tab_name||'" ("' || col_name|| '") values(?)') (:col_value);
    else
        status=0;
END

使用单个(动态创建的)MERGE statement,您可以进一步简化此操作。