在嵌入式SQL中使用变量来表示数据库文件,使用自由格式的RPG。

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

Using a variable for a database file in embeded SQL in free RPG

问题

我想编写一个SQL语句,无论想要的数据文件是什么,都可以正常工作。
示例:

exec sql select * from :variable;

我在“:”处遇到了SQL0104错误
“令牌无效。有效令牌:(NEW FINAL TABLE UNNEST LATERAL MLTABLE JSON_TABLE<IDENTIFIER>)”

我尝试在不同的语句中使用“insert into :variable”,但我仍然遇到相同的错误。
也许这是不可能的,我必须将数据库文件硬编码到我的代码中,或者是否有其他方法可以绕过这个问题?
谢谢

英文:

I would like to write an sql statment, that works no matter what data file is wanted.
example:

exec sql select * from :variable;

I am getting a SQL0104 Error at the ":"
"Token not vaild. Valid Token :(NEW FINAL TABLE UNNEST LATERAL MLTABLE JSON_TABLE<IDENTIFIER>"

I tried to do it in different statemenst with "insert into :variable", but I get the same Error.
Is it maybe not possible and I have to hard code the databasefile into my code or is there a way around?
Thanks

答案1

得分: 2

您不能使用具有可变表名的静态SQL。

您需要使用EXECUTE IMMEDIATEPREPAREEXECUTE来使用动态SQL。

  1. wMySql = 'insert into ' + wTableName + ' values (1, ''ABC'')';
  2. exec SQL
  3. execute immediate :wMySql;

请注意,SELECT * FROM TABLE不是可以动态运行的语句。就此而言,静态版本没有意义。SELECT ... INTO :myData FROM MYTABLE是有效的静态语句,但不能动态使用。相反,您需要使用VALUES (SELECT * from MYTABLE) into :myData,这可以动态运行。

这里是一个使用动态SQL的IBM示例。通常情况下,您会在循环中看到FETCH以返回多行,如写入的情况下,这将仅返回第一行然后结束。这还展示了在语句中使用替代变量?的用法。这是一种最佳实践,因为它可以防止SQL注入攻击。但请注意,您不能将替代变量用于表名或列名。

  1. //**************************************************
  2. //* 声明程序变量。 *
  3. //* STMT初始化为 *
  4. //* 列出的SQL语句。 *
  5. //**************************************************
  6. DCL-S EMPNUM CHAR(6);
  7. DCL-S NAME CHAR(15);
  8. DCL-S STMT CHAR(500)
  9. INZ('SELECT LASTNAME FROM CORPDATA.EMPLOYEE +
  10. WHERE EMPNO = ?');
  11. ...
  12. //**********************************************************
  13. //* 根据声明部分中初始化的STMT准备STMT *
  14. //**********************************************************
  15. EXEC SQL PREPARE S1 FROM :STMT;
  16. //*************************************
  17. //* 为STMT声明游标 *
  18. //*************************************
  19. EXEC SQL DECLARE C1 CURSOR FOR S1;
  20. //*******************************************************
  21. //* 分配员工号以在选择语句中使用 *
  22. //*******************************************************
  23. EMPNUM = '000110';
  24. //**********************
  25. //* 打开游标 *
  26. //**********************
  27. EXEC SQL OPEN C1 USING :EMPNUM;
  28. //*********************************************
  29. //* 检索记录并将LASTNAME的值放入NAME *
  30. //*********************************************
  31. EXEC SQL FETCH C1 INTO :NAME;
  32. //******************************
  33. //* 在这里处理NAME的程序 *
  34. //******************************
  35. ...
  36. //******************
  37. //* 关闭游标 *
  38. //******************
  39. EXEC SQL CLOSE C1;
英文:

You can't use static SQL with a variable table name.

You'd need to use dynamic SQL via EXECUTE IMMEDIATE or PREPARE and EXECUTE

  1. wMySql = &#39;insert into &#39; + wTableName + &#39; values (1,&#39;&#39;ABC&#39;&#39;)&#39;;
  2. exec SQL
  3. execute immediate :wMySql;

Note that SELECT * FROM TABLE is not a statement that can be dynamically run. For that matter, a static version doesn't make sense. SELECT ... INTO :myData FROM MYTABLE is a valid static statement, but can't be used dynamically. Instead you'd need to use VALUES (SELECT * from MYTABLE) into :myData which can be run dynamically.

Here's an IBM example using dynamic SQL.
Note normally you'd see the FETCH in a loop to return multiple rows, as written this will just return the first row then end. This also show the use of replacement variables ? in the statement. Which is a best practice as it prevents SQL injection attacks. However note that you can't use a replacement variable for the table name or column names.

  1. //**************************************************
  2. //* Declare program variables. *
  3. //* STMT initialized to the *
  4. //* listed SQL statement. *
  5. //**************************************************
  6. DCL-S EMPNUM CHAR(6);
  7. DCL-S NAME CHAR(15);
  8. DCL-S STMT CHAR(500)
  9. INZ(&#39;SELECT LASTNAME FROM CORPDATA.EMPLOYEE +
  10. WHERE EMPNO = ?&#39;);
  11. ...
  12. //*************************************************************
  13. //* Prepare STMT as initialized in declare section *
  14. //*************************************************************
  15. EXEC SQL PREPARE S1 FROM :STMT;
  16. //*************************************
  17. //* Declare Cursor for STMT *
  18. //*************************************
  19. EXEC SQL DECLARE C1 CURSOR FOR S1;
  20. //*****************************************************
  21. //* Assign employee number to use in select statement *
  22. //*****************************************************
  23. EMPNUM = &#39;000110&#39;;
  24. //**********************
  25. //* Open Cursor *
  26. //**********************
  27. EXEC SQL OPEN C1 USING :EMPNUM;
  28. //***********************************************
  29. //* Fetch record and put value of *
  30. //* LASTNAME into NAME *
  31. //***********************************************
  32. EXEC SQL FETCH C1 INTO :NAME;
  33. //********************************
  34. //* Program processes NAME here *
  35. //********************************
  36. ...
  37. //******************
  38. //* Close cursor *
  39. //******************
  40. EXEC SQL CLOSE C1;

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

发表评论

匿名网友

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

确定