2013-06-26 5 views
3

Переключение на Oracle с SQL Server. Как связать строку с переменной внутри цикла? В 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 до сих пор в своей хранимой процедуре. (Переход к эволюционирует к автогеном для ClassMap файлов для 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

ЧТО ТАКОЕ ВСЕ ДОВОДЫ ПЕРЕД переменными? Не думайте, что вам это нужно. Во всяком случае, вы уже используете оператор concat, ||, поэтому для переменной x будет «x: = x || ;» – OldProgrammer

ответ

1

Если вы хотите сделать это со значением build_sql в процедуре, пропустить ведущую двоеточие. Это для параметризованного значения, которое здесь не применяется.

Также объявляем длину переменной в верхней части. Это немного запутанно, потому что вы можете оставить длину для параметров, но вам нужна длина для объявленной переменной.

Вот вырезанная версия вашего профа, показывающая манипуляции 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 вместо функции ||.