存储过程错误 “绑定变量未设置”

huangapple go评论124阅读模式
英文:

STORED PROCEDURE ERROR "BIND VARIABLE NOT SET"

问题

我尝试在Snowflake中运行以下存储过程,但我遇到了绑定变量错误:

```sql
CREATE OR REPLACE PROCEDURE sp_name(TASKNUM FLOAT)
RETURNS STRING
LANGUAGE SQL

AS
$$
DECLARE
  sqlcom STRING;
 
BEGIN
  
  sqlcom := 'INSERT INTO task_tracker VALUES (''TASK_SP_CALL'' || :TASKNUM, CURRENT_TIMESTAMP(), ''Task Done - TASK_SP_CALL Remarks'', ''Active'')';
  EXECUTE IMMEDIATE sqlcom;
  
  RETURN 'Succeeded';
  
EXCEPTION
    WHEN OTHER THEN
    RETURN 'Failed: ' || SQLERRM;
END;

$$;

当我执行这个:

call sp_name(2)

我得到:

SQL 编译错误
未设置绑定变量 :task_num。
当我在存储过程内部硬编码数值时,它可以工作。


<details>
<summary>英文:</summary>

I try to run in Snowflake the below stored procedure but I get the bind variable error:

CREATE OR REPLACE PROCEDURE sp_name(TASKNUM FLOAT)
RETURNS STRING
LANGUAGE SQL

AS
$$
DECLARE
sqlcom STRING;

BEGIN

sqlcom := 'INSERT INTO task_tracker VALUES (''TASK_SP_CALL'' || :TASKNUM, CURRENT_TIMESTAMP(), ''Task Done - TASK_SP_CALL Remarks'', ''Active'')';
EXECUTE IMMEDIATE sqlcom;

RETURN 'Succeeded';

EXCEPTION
WHEN OTHER THEN
RETURN 'Failed: ' || SQLERRM;
END;

$$;


When I execute this:  

    call sp_name(2)

I get: 

&gt; SQL compilation error    
&gt; Bind variable :task_num not set.

When I hard code the value inside the stored procedure, it works.

</details>


# 答案1
**得分**: 2

动态SQL字符串应该使用参数占位符 - `?` 进行参数化,并使用 `EXECUTE IMMEDIATE sql USING (var1)` 调用:

```sql
CREATE OR REPLACE PROCEDURE sp_name(TASKNUM FLOAT)
RETURNS STRING
LANGUAGE SQL
AS
DECLARE
  sqlcom STRING;
BEGIN
  sqlcom := 'INSERT INTO task_tracker VALUES (''TASK_SP_CALL'' || ?,
                                              CURRENT_TIMESTAMP(),
                                              ''Task Done - TASK_SP_CALL Remarks'',
                                              ''Active'')';
  EXECUTE IMMEDIATE sqlcom USING (TASKNUM);
  
  RETURN 'Succeeded';  
EXCEPTION
    WHEN OTHER THEN
    RETURN 'Failed: ' || SQLERRM;
END;

CALL sp_name(1);
-- Succeeded

注意:

  1. "Blind insert" 是一种反模式,应提供明确的列列表 - INSERT INTO task_tracker(col1, col2, ...)
  2. INSERT INTO ... VALUES (...) 仅允许常量或简单表达式,如果使用更复杂的函数,则应考虑使用 INSERT INTO ... SELECT ...
英文:

The dynamic SQL string should be parametrized with parameter placeholders - ? and invoked with EXECUTE IMMEDIATE sql USING (var1):

CREATE OR REPLACE PROCEDURE sp_name(TASKNUM FLOAT)
RETURNS STRING
LANGUAGE SQL
AS
DECLARE
  sqlcom STRING;
BEGIN
  sqlcom := &#39;INSERT INTO task_tracker VALUES (&#39;&#39;TASK_SP_CALL&#39;&#39; || ?,
                                              CURRENT_TIMESTAMP(),
                                              &#39;&#39;Task Done - TASK_SP_CALL Remarks&#39;&#39;,
                                              &#39;&#39;Active&#39;&#39;)&#39;;
  EXECUTE IMMEDIATE sqlcom USING (TASKNUM);
  
  RETURN &#39;Succeeded&#39;;  
EXCEPTION
    WHEN OTHER THEN
    RETURN &#39;Failed: &#39; || SQLERRM;
END;

CALL sp_name(1);
-- Succeeded

Notes:

  1. "Blind insert" is an antipattern and explicit column list should be provided - INSERT INTO task_tracker(col1, col2, ...)
  2. INSERT INTO ... VALUES (...) allows only for constants or simple expressions, if more complex functions are used then INSERT INTO ... SELECT ... should be considered

huangapple
  • 本文由 发表于 2023年7月17日 10:34:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76701201.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定