2013-06-26 73 views
3

從SQL Server切換到Oracle。如何將字符串連接到循環內的變量?在SQL Server中,我會寫類似於Oracle相當於T-SQL SET @var = @var +'';

DECLARE @var varchar(max); 
WHILE ([I'm doing something or whatever on a table]) 
BEGIN 
    SET @var = @var + ' additional text'; 
END 
SELECT @var AS 'result'; 

這是我在Oracle存儲過程中使用的存儲過程。如果你想在過程中的build_sql值要做到這一點,離開了領導冒號(將其演變爲類映射文件的AUTOGEN NHibernate的)

CREATE OR REPLACE PROCEDURE WWNA.UT_MAPPINGHELPER 
(
    TABLE_NAME IN ALL_TABLES.TABLE_NAME%TYPE 
    , OWNER_NAME IN ALL_TABLES.OWNER%TYPE 
    , CLASS_DEFINITION IN OUT VARCHAR2 
) 
    IS 
    CURSOR TABLE_INFO_CUR 
    IS 
    SELECT 
     T.TABLE_NAME 
     , C.COLUMN_NAME 
     ,C.DATA_TYPE 
     ,C.DATA_LENGTH 
     ,C.DATA_PRECISION 
     ,C.NULLABLE 
    FROM 
     ALL_TABLES T 
     JOIN 
     ALL_TAB_COLUMNS C 
      ON T.TABLE_NAME = C.TABLE_NAME 
       AND T.OWNER = C.OWNER 
    WHERE 
     T.TABLE_NAME = :TABLE_NAME 
     AND T.OWNER = :OWNER_NAME; 
    TABLE_INFO_ROW TABLE_INFO_CUR%ROWTYPE; 
    build_sql varchar2; 
BEGIN 
    --VARIABLE build_sql varchar2(4000); 
    :build_sql := ''; 
    OPEN TABLE_INFO_CUR; 

    LOOP 
     FETCH TABLE_INFO_CUR INTO TABLE_INFO_ROW; 
     EXIT WHEN TABLE_INFO_CUR%NOTFOUND; 
     SELECT (:build_sql || ' ' || TABLE_INFO_ROW.TABLE_NAME || ' ' || TABLE_INFO_ROW.COLUMN_NAME || ' ' || TABLE_INFO_ROW.DATA_TYPE) INTO :build_sql; 
    END LOOP; 
    :CLASS_DEFINITION := :build_sql; 

    --DBMS_OUTPUT.put_line (CLASS_DEFINITION); 


END; 

感謝

+1

什麼是w /變量之前的所有冒號?不要以爲你需要那樣。無論如何,你已經使用了concat操作符||,所以對於變量x,將是「x:= x || ;」 – OldProgrammer

回答

1

。這是爲了一個參數值,這不適用於此。

還聲明build_sql變量的長度在頂部。這有點令人困惑,因爲您可以忽略參數的長度,但是您需要長度來爲已聲明的變量執行該操作。

這是您的proc的切碎版本,顯示build_sql操作。還要注意的是,CLASS_DEFINITION參數變量不應該有冒號前綴之一:

CREATE OR REPLACE PROCEDURE WWNA.UT_MAPPINGHELPER 
(
    TABLE_NAME IN ALL_TABLES.TABLE_NAME%TYPE 
    , OWNER_NAME IN ALL_TABLES.OWNER%TYPE 
    , CLASS_DEFINITION IN OUT VARCHAR2 
) 
IS 
    ... 
    build_sql varchar2(4000); 
BEGIN 
    build_sql := ''; 
    ... 
    LOOP 
     build_sql := build_sql || 'whatever'; 
    END LOOP; 
    CLASS_DEFINITION := build_sql; 
END; 

還要注意的是,你不需要build_sql := ''行 - 變量值將默認爲空白。或聲明的時候,你可以指定一個初始值:

CREATE OR REPLACE PROCEDURE WWNA.UT_MAPPINGHELPER 
(
    TABLE_NAME IN ALL_TABLES.TABLE_NAME%TYPE 
    , OWNER_NAME IN ALL_TABLES.OWNER%TYPE 
    , CLASS_DEFINITION IN OUT VARCHAR2 
) 
IS 
    ... 
    build_sql varchar2(4000) := 'start of my sql'; 
BEGIN 
    ... 
+0

'build_sql:='''和'build_sql:= NULL'是等價的。在Oracle中,零長度字符串與NULL相同。因此'build_sql:=''; IF build_sql IS NULL THEN DBMS_OUTPUT.PUT_LINE('是,它是NULL');'將打印'是的,它是NULL'。 –

+0

優秀點。連接工作的方式(變量未初始化或變量初始化爲''''),所以我決定不提出整個「空字符串爲空」的東西,但你讓我想我應該有 - 這是一個真正的難題適用於從SQL Server(或MySQL)遷移到Oracle的用戶。 –

2
CREATE OR REPLACE PROCEDURE WWNA.UT_MAPPINGHELPER 
(
    TABLE_NAME IN ALL_TABLES.TABLE_NAME%TYPE 
    , OWNER_NAME IN ALL_TABLES.OWNER%TYPE 
    , CLASS_DEFINITION IN OUT VARCHAR2 
) 
    IS 
    CURSOR TABLE_INFO_CUR 
    IS 
    SELECT 
     T.TABLE_NAME 
     , C.COLUMN_NAME 
     ,C.DATA_TYPE 
     ,C.DATA_LENGTH 
     ,C.DATA_PRECISION 
     ,C.NULLABLE 
    FROM 
     ALL_TABLES T 
     JOIN 
     ALL_TAB_COLUMNS C 
      ON T.TABLE_NAME = C.TABLE_NAME 
       AND T.OWNER = C.OWNER 
    WHERE 
     T.TABLE_NAME = :TABLE_NAME 
     AND T.OWNER = :OWNER_NAME; 

    build_sql varchar2(32767); 
BEGIN 
    --build_sql := ''; --Not needed, build_sql is already initialised to NULL 


    FOR cur_rec IN TABLE_INFO_CUR 
    LOOP 
     build_sql := build_sql || ' ' || 
        cur_rec.TABLE_NAME || ' ' || 
        cur_rec.COLUMN_NAME || ' ' || 
        cur_rec.DATA_TYPE; 
    END LOOP; 
    CLASS_DEFINITION := build_sql; 

    --DBMS_OUTPUT.put_line (CLASS_DEFINITION); 


END; 

你需要定義變量CLASS_DEFINITION。使用CURSOR FOR LOOP負責光標的打開和關閉,以及批量獲取結果。

您也可以使用CONCAT函數代替||函數。