將字元串連接到變數以用作查詢中的列名
我有一個過程,我查詢表 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 ;