【问题标题】:PL/SQL Extract Column Names and use in select statementPL/SQL 提取列名并在 select 语句中使用
【发布时间】:2018-03-13 01:23:11
【问题描述】:

亚行表

今天日期

我有一张 ADB 表。我想根据系统日期提取列名

我目前正在尝试以下不起作用。

SELECT (
        SELECT DISTINCT TO_CHAR(TODAY, 'MON') || '_' || TO_CHAR(TODAY, 'D') AS TODAY
        FROM STTM_DATES
        )
FROM adb

我正在尝试这个脚本,但没有结果集。

SQLSTMT VARCHAR2(2000); 
SQLSTMT := 'SELECT' || ' ' || (SELECT DISTINCT TO_CHAR(TODAY,'MON') || '_' || TO_CHAR(TODAY,'D')AS TODAY FROM STTM_DATES)||' ' || 'FROM ADB'; 
EXECUTE IMMEDIATE SQLSTMT; 

【问题讨论】:

  • 你的桌子设计对我来说看起来不是最理想的。不要将每一天存储在单独的列中,这不会扩展,并且会导致需要 hack,而是将所有时间戳存储在单个列中。然后,您可以轻松地使用WHERE 子句在该列中搜索当天。
  • 我将使用此脚本每天更新 adb,这就是为什么我要获取列..content ADB 表是 CUST_AC_NO JAN_2 JAN_3 JAN_4 JAN_5 JAN_6 JAN_7....Dec 31
  • 我的话被置若罔闻,因为我认为您需要修复您的餐桌设计。 不要将一天存储在单独的列中,所有天都使用一个列。
  • 我正在尝试这个脚本,但没有结果集。 SQLSTMT VARCHAR2(2000); SQLSTMT := '选择' || ' ' || (SELECT DISTINCT TO_CHAR(TODAY,'MON') || '_' || TO_CHAR(TODAY,'D')AS TODAY FROM STTM_DATES)||' ' || '来自亚行';立即执行 SQLSTMT;
  • 重要提示:请不要张贴样本数据和结果集的图像。只需复制粘贴为纯文本即可。你的桌子设计看起来很糟糕,你需要修复它。如果实施,您正在寻找的解决方案实际上可能会使它变得更加混乱。

标签: sql oracle plsql oracle11g


【解决方案1】:

如果您只得到一行,则需要一个目标来存储该结果(和一个 INTO 表达式),例如

SQL> create table t ( a1 int, a2 int, a3 int );

Table created.

SQL>
SQL> insert into t values (1,2,3);

1 row created.

SQL>
SQL> set serverout on
SQL> declare
  2    col_name varchar2(30);
  3    result int;
  4  begin
  5    col_name := 'a1';
  6    execute immediate 'select '||col_name||' from t' into result;
  7    dbms_output.put_line(result);
  8
  9    col_name := 'a2';
 10    execute immediate 'select '||col_name||' from t' into result;
 11    dbms_output.put_line(result);
 12  end;
 13  /
1
2

PL/SQL procedure successfully completed.

如果您收到一组行,则需要循环浏览游标。

SQL>
SQL> insert into t values (4,5,6);

1 row created.

SQL>
SQL>
SQL> set serverout on
SQL> declare
  2    col_name varchar2(30) := 'a3';
  3    result int;
  4    rc sys_refcursor;
  5  begin
  6    open rc for 'select '||col_name||' from t';
  7    loop
  8      fetch rc into result;
  9      exit when rc%notfound;
 10      dbms_output.put_line(result);
 11    end loop;
 12    close rc;
 13  end;
 14  /
3
6

PL/SQL procedure successfully completed.

SQL>
SQL>

但这些都不能解决其他人对这里潜在设计问题表达的担忧。

【讨论】:

    【解决方案2】:
    CREATE TABLE CUSTDET(CUSTACNO NUMBER, DT DATE, VAL NUMBER);
    INSERT INTO CUSTDET VALUES(1, SYSDATE-2, 10);
    INSERT INTO CUSTDET VALUES(1, SYSDATE-1, 20);
    INSERT INTO CUSTDET VALUES(1, SYSDATE, 30);
    INSERT INTO CUSTDET VALUES(2, SYSDATE-2, 40);
    INSERT INTO CUSTDET VALUES(3, SYSDATE-1, 10);
    INSERT INTO CUSTDET VALUES(3, SYSDATE, 20);
    COMMIT;
    

    您不需要为此使用动态 sql。

    SELECT TO_CHAR(dt,'MON')||'_'||TO_CHAR(dt,'D') AS today FROM custdet;
    

    输出:

    TODAY
    MAR_1
    MAR_2
    MAR_3
    MAR_1
    MAR_2
    MAR_3
    

    如果要使用动态sql,需要在变量或表变量中接收输出以单独显示。

    DECLARE
        SQLSTMT VARCHAR2(2000); 
        TYPE MYTABTYP IS TABLE OF VARCHAR2(10);
        MYTABVAR MYTABTYP := MYTABTYP();
    BEGIN
        SQLSTMT := q'[SELECT TO_CHAR(dt,'MON')||'_'||TO_CHAR(dt,'D') AS today FROM custdet]';
        EXECUTE IMMEDIATE SQLSTMT BULK COLLECT INTO MYTABVAR;
        FOR idx IN MYTABVAR.FIRST..MYTABVAR.LAST
        LOOP
            DBMS_OUTPUT.PUT_LINE(MYTABVAR(idx));
        END LOOP;
    END;
    

    输出:

    MAR_1
    MAR_2
    MAR_3
    MAR_1
    MAR_2
    MAR_3
    

    【讨论】:

      猜你喜欢
      • 2018-03-13
      • 1970-01-01
      • 1970-01-01
      • 2017-03-29
      • 1970-01-01
      • 2013-06-14
      • 1970-01-01
      • 2010-09-17
      相关资源
      最近更新 更多