【问题标题】:Oracle equivalent of T-SQL SET @var = @var + ' ';Oracle 等价于 T-SQL SET @var = @var + ' ';
【发布时间】:2013-06-24 01:45:50
【问题描述】:

从 SQL Server 切换到 Oracle。如何将字符串连接到循环内的变量?在 SQL Server 中,我会写类似

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 中的存储过程中的内容。 (将其演变为 NHibernate 的 ClassMap 文件的自动生成器)

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;

谢谢

【问题讨论】:

  • 变量前的所有冒号是什么?不要认为你需要那个。无论如何,您已经在使用 concat 运算符 ||,因此对于变量 x,将是 "x := x || ;"

标签: sql sql-server oracle plsql oracle11g


【解决方案1】:

如果您想在过程中使用build_sql 值执行此操作,请省略前导冒号。这是一个参数化的值,这里不适用。

还要在顶部声明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
   ...

【讨论】:

  • build_sql := ''build_sql := NULL 是等价的。在 Oracle 中,长度为零的字符串与 NULL 相同。因此build_sql := ''; IF build_sql IS NULL THEN DBMS_OUTPUT.PUT_LINE('Yep, it's NULL'); 将打印Yep, it's NULL
  • 好点。串联工作任何一种方式(变量未初始化或变量初始化为'')所以我决定不提出整个“空字符串为空”的事情,但你让我认为我应该有 - 这是一个真正的陷阱用户从 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 函数代替|| 函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 2012-03-12
    • 2021-08-04
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 2016-07-07
    相关资源
    最近更新 更多