【问题标题】:IBM Informix How to pass string value in parameterIBM Informix 如何在参数中传递字符串值
【发布时间】:2018-01-16 08:42:58
【问题描述】:

谁能帮我为 Informix db 创建正确的 SQL 查询? 我有一个函数,我正在尝试从 Informix 文档中描述的字符串准备 SQL 查询

CREATE FUNCTION somefunction( stringval VARCHAR( 32 )) RETURNING INT;
DEFINE c_query varchar(250);
LET c_query = 'select first 1 someid, somevalue from sometable where sname= '||stringval||' order by somevalue;
PREPARE c_stmt
FROM c_query;

DECLARE c_cur CURSOR FOR c_stmt;
OPEN c_cur ;
FETCH c_cur INTO sp_id ;
CLOSE c_cur;
FREE c_cur;
FREE c_stmt;
RETURN sp_id;
END FUNCION;

当我尝试测试它时,我按如下方式调用它:

SELECT * FROM table(functionname('fo'))

但不幸的是,我收到带有文本的错误消息:

Column (fo) not found in any table in the query (or SLV is undefined).

我做错了什么?

【问题讨论】:

  • 在这种情况下,我收到与没有引号相同的错误消息
  • 当我尝试硬编码字符串而不是参数时,我得到了同样的错误
  • '从 sometable 中选择前 1 个 someid where sname= '||'stringval';返回相同的错误信息
  • 我不能,因为查询是从字符串准备的,如上面的代码所示,它的文本用引号括起来
  • 这只是代码示例,我已经修复了它

标签: sql informix


【解决方案1】:

如果您想要与名称 fo 对应的数字,则必须将其括在引号中,这反过来意味着您需要转义字符串中的引号。您需要阅读有关 SQL Injection 的信息,因为您提出的建议很容易受到 SQL 注入的影响。

如果练习的目的是执行显示的查询,那么你应该使用:

CREATE FUNCTION somefunction(stringval VARCHAR(32)) RETURNING INT;

    DEFINE sp_id INTEGER;

    SELECT FIRST 1 someid
      INTO sp_id
      FROM sometable
     WHERE sname= stringval
     ORDER BY somevalue;

    RETURN sp_id;

END FUNCTION

如果练习的对象是使用动态 SQL,那么你应该考虑使用占位符,像这样:

CREATE FUNCTION somefunction(stringval VARCHAR(32)) RETURNING INT;

    DEFINE sp_id INTEGER;
    DEFINE c_query varchar(250);
    LET c_query = 'SELECT FIRST 1 someid FROM sometable WHERE sname = ? ORDER BY somevalue';
    PREPARE c_stmt FROM c_query;

    DECLARE c_cur CURSOR FOR c_stmt;
    OPEN c_cur USING stringval;
    FETCH c_cur INTO sp_id;
    CLOSE c_cur;
    FREE c_cur;
    FREE c_stmt;
    RETURN sp_id;

END FUNCTION

在您的桌子上未经测试。我测试的代码是:

CREATE FUNCTION atomic_number(symbol VARCHAR(3)) RETURNING INTEGER;
    DEFINE num INTEGER;
    SELECT atomic_number INTO num FROM elements AS e WHERE e.symbol = symbol;
    RETURN num;
END FUNCTION

和:

CREATE FUNCTION atomic_number(symbol VARCHAR(3)) RETURNING INTEGER;
    DEFINE num INTEGER;
    DEFINE c_query varchar(250);
    LET c_query = 'SELECT FIRST 1 atomic_number FROM elements WHERE symbol = ? ORDER BY atomic_number';
    PREPARE c_stmt FROM c_query;

    DECLARE c_cur CURSOR FOR c_stmt;
    OPEN c_cur USING symbol;
    FETCH c_cur INTO num;
    CLOSE c_cur;
    FREE c_cur;
    FREE c_stmt;
    RETURN num;
END FUNCTION

这些针对“元素表”(如“周期表”),其结构:

CREATE TABLE elements
(
    atomic_number   INTEGER NOT NULL PRIMARY KEY
                    CHECK (atomic_number > 0 AND atomic_number < 120),
    symbol          CHAR(3) NOT NULL UNIQUE,
    name            CHAR(20) NOT NULL UNIQUE,
    atomic_weight   DECIMAL(8, 4) NOT NULL,
    pt_period       SMALLINT NOT NULL
                    CHECK (pt_period BETWEEN 1 AND 7),
    pt_group        CHAR(2) NOT NULL
                    -- 'L' for Lanthanoids, 'A' for Actinoids
                    CHECK (pt_group IN ('1', '2', 'L', 'A', '3', '4', '5', '6',
                                        '7', '8', '9', '10', '11', '12', '13',
                                        '14', '15', '16', '17', '18')),
    stable          CHAR(1) DEFAULT 'Y' NOT NULL
                    CHECK (stable IN ('Y', 'N'))
);

INSERT INTO elements VALUES(  1, 'H',   'Hydrogen',        1.0079, 1, '1',  'Y');
…
INSERT INTO elements VALUES(118, 'Og',  'Oganesson',     294.2100, 7, '18', 'N');

【讨论】:

  • 当我尝试使用SELECTORDER BY 来分配带有LETINTO 的值时,我得到了-201 A syntax error has occurred,所以它似乎不能直接完成(因为提到的OP)。但是,我可以使用表表达式将 ORDER BY 包装为一种解决方法(不知道它对性能有什么影响)。
  • @LuísMarques:在最好的情况下,编写 SPL 是一种“追逐语法错误”的令人不快的游戏。我不能说你为什么会遇到问题。我在运行 macOS High Sierra 10.13.2 的 MacBook Pro 上使用 Informix 12.10.FC6 进行了测试。现在,我没有使用 ORDER BY 子句测试单例 SELECT,但我确实使用它测试了动态 SQL。对我来说效果很好。你是在什么系统上测试的?确切的语法是什么? (考虑使用电子邮件:查看我的个人资料。)
  • @LuísMarques:第二个存储过程中缺少引号。我已经更新了答案来解决这个问题。
  • 在函数上下文中使用order by子句的唯一方法是动态sql。
  • 为什么要使用SELECT 而不是EXECUTE FUNCTION somefunction('fo')?如果动态 SQL 允许您使用 ORDER BY 而静态 SQL 不允许,这是一个令人讨厌的不一致。要么都应该允许,要么都不允许。然而,令人讨厌的不一致确实会发生。如果您愿意,可以使用动态 SQL。没有什么可以阻止您在 USING 子句中多次使用相同的参数,从而将输入参数之一“分配”给多个占位符。二只是“许多”的一个相当有限的情况。
猜你喜欢
  • 1970-01-01
  • 2020-09-30
  • 2021-03-05
  • 1970-01-01
  • 1970-01-01
  • 2011-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多