3

テーブルに挿入する前に、レコードの存在を確認しようとしています。

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
:

なぜそれが未知のトークンなのですか?入力パラメーターを使用しようとしています。

4

1 に答える 1

2

選択した場合のように、オブジェクト名 (テーブル名、列名など) を直接パラメーター化することはできません。パラメータは値にのみ使用できます。

オブジェクト名をパラメーター化する場合は、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ステートメントを使用すると、これをさらに単純化できる場合があります。

于 2015-05-12T18:34:15.817 に答える