Stored-Procedures

將字元串連接到變數以用作查詢中的列名

  • May 9, 2021

我有一個過程,我查詢表 a 並創建這樣的變數

SELECT TRCODE , COLA , COLB , COLC , COLD
INTO TRANSACTION_TYPE , HOURS , RATE , FACTOR , APPROPRIATION
FROM PR . PREXEC
WHERE USRID = USER_NUMBER ;

撥款變數包含一個字元,它是一個從 1 到 4 的數字。

我還有一張叫做 pr.earnings 的桌子。在該表中,我有一個名為 APPROP1 到 APPROP4 的列。在同一過程中,我需要通過獲取字元串“APPROP”並連接查詢中的APPROPRIATION 變數來查詢pr.earnings。

我試過

select concat('APPROP',APPROPRIATION)

FROM PR.EARNIGS;

我想要的結果select APPROP1 FROM PR.EARNINGS;是我得到了一個系統創建的列,其中包含 APPROP1。我不知道如何將字元串連接到要在查詢中使用的變數。

我嘗試了使用動態 sql,但由於我不知道自己在做什麼而不斷出錯。如何連接字元串和變數以將其用作 sql 查詢中的列名?

根據 Lennart 的建議,我現在有這個

SET STMT = 'SELECT APPROP' || appropriation || ' pr.earnings into ' || active_appropriation ||
              ' where empnumber = ' || user_number;
   EXECUTE IMMEDIATE STMT

我試圖像這樣插入active_appropriation

insert into pr.worksheet (W_EMPLOYEE_NUMBER, W_TRANSACTION_TYPE, W_HOURS, W_RATE, W_APPROPRIATION)
   values (user_number, transaction_type, hours, rate, active_appropriation);

我收到錯誤“變數不能為空”,我假設它是 active_appropriation 值。

我讓它工作。這是我的解決方案。

   SET STMT2 = 'VALUES (SELECT approp' || appropriation ||
   'FROM pr.earnings where empnumber = ' || user_number || ') INTO ?';
PREPARE S2 from stmt2;
EXECUTE S2 using active_appropriation;

您的查詢的問題是您需要使用數據構造元數據(列的名稱)。因此,您需要首先構造查詢,然後使用動態 SQL 執行它。類似的東西(未經測試)

CREATE PROCEDURE P
LANGUAGE SQL
BEGIN
   DECLARE STMT VARCHAR(100);
   DECLARE APPROP CHAR(1);

   SELECT APPROPRIATION INTO APPROP FROM ...;
   SET STMT = 'SELECT APPROP' || APPROP || ' FROM ... ';
   EXECUTE IMMEDIATE STMT;
END @

我使用 @ 作為語句終止符。請注意,編譯器無法驗證查詢是否有意義,因此您最終可能會遇到執行時錯誤。

調試儲存過程

IBM Datastudio 有一個成熟的儲存過程調試器,即你可以設置斷點,檢查變數等。如果你因為某種原因不想安裝它(或者像我一樣,找不到下載頁面:-),你可以使用DBMS_OUTPUT模組:

~]$ # add some sample data
~]$ db2 "create table t (APPROPRIATION char(1) not null)"
~]$ db2 "insert into t (APPROPRIATION) values ('1')"
~]$ db2 "insert into t (APPROPRIATION) values ('2')"
~]$ db2 "insert into t (APPROPRIATION) values ('3')"
~]$ db2 "insert into t (APPROPRIATION) values ('4')"

~]$ cat p.sql 
CREATE PROCEDURE P()
LANGUAGE SQL
BEGIN
   DECLARE STMT VARCHAR(100);
   DECLARE APPROP CHAR(1);

   SELECT APPROPRIATION INTO APPROP FROM T ORDER BY RAND() FETCH FIRST 1 ROWS ONLY;
   SET STMT = 'SELECT APPROP' || APPROP || ' FROM ...';
   call dbms_output.put_line('DEBUG: ' || STMT);
   -- EXECUTE IMMEDIATE STMT;
END @

~]$ db2 -td@ -f p.sql

~]$ db2 "SET SERVEROUTPUT ON"
DB20000I  The SET SERVEROUTPUT command completed successfully.
~]$ db2 "CALL P()"

 Return Status = 0

DEBUG: SELECT APPROP1 FROM ...
~]$ db2 "CALL P()"

 Return Status = 0

DEBUG: SELECT APPROP1 FROM ...
~]$ db2 "CALL P()"

 Return Status = 0

DEBUG: SELECT APPROP2 FROM ...
~]$ db2 "CALL P()"

 Return Status = 0

DEBUG: SELECT APPROP1 FROM ...
~]$ db2 "CALL P()"

 Return Status = 0

DEBUG: SELECT APPROP3 FROM ...

~]$ db2 "SET SERVEROUTPUT OFF"
   

另一種選擇是使用 out 變數:

~]$ cat p2.sql 
CREATE PROCEDURE P2(OUT outstmt VARCHAR(100))
LANGUAGE SQL
BEGIN
   DECLARE STMT VARCHAR(100);
   DECLARE APPROP CHAR(1);

   SELECT APPROPRIATION INTO APPROP FROM T ORDER BY RAND() FETCH FIRST 1 ROWS ONLY;
   SET STMT = 'SELECT APPROP' || APPROP || ' FROM ...';
   SET outstmt = stmt;
   call dbms_output.put_line('DEBUG: ' || STMT);
   -- EXECUTE IMMEDIATE STMT;
END @

~]$ db2 -td@ -f p2.sql

~]$ db2 "CALL P2(?)"

 Value of output parameters
 --------------------------
 Parameter Name  : OUTSTMT
 Parameter Value : SELECT APPROP1 FROM ...

 Return Status = 0

這兩種方法的一個主要缺點是,當您最需要它時,即當您的過程失敗時,它們不會產生任何輸出。

對於以後的文章,請始終包含可重現的設置。要麼包括 DDL(創建表語句等)和 SQL(插入表語句),要麼使用DB<>Fiddle 之類的服務。

大多數人(包括我自己)通常只是跳到下一個問題,除非有一種簡單的方法可以重現問題。您不僅會得到更多答案,而且自從您定義了設置後,它們也可以隨時使用。到目前為止,如果我的答案對您完全有用,那麼您將不得不根據您的實際設置對其進行調整,因為我發明了一些假想的表格等。

這行得通嗎?

SELECT TRCODE , COLA , COLB , COLC , 'APPROP' || COLD
INTO TRANSACTION_TYPE , HOURS , RATE , FACTOR , APPROPRIATION
FROM PR . PREXEC
WHERE USRID = USER_NUMBER ;

引用自:https://dba.stackexchange.com/questions/291213