1

我在创建 PL/SQL 块时遇到了一些困难。我的脚本的目的是根据表中上个月的总数提取报告(已创建为表名“countpull”)。我想在我的脚本中使用月份的名称来创建表,但是 Oracle 返回错误“ORA-00900:无效的 SQL 语句”,指向下面的 CREATE TABLE 命令。

DECLARE
  curMonthChar NVARCHAR2(25);
  curTableName NVARCHAR2(50);
  tableexists NUMBER := 0;

BEGIN
  SELECT TO_CHAR(ADD_MONTHS(sysdate,-1),'fmMONTH') INTO curMonthChar FROM DUAL;
  SELECT ('QP17414_'||curMonthChar) INTO curTableName FROM DUAL;

  --Check to see if current month's count table exists
  SELECT COUNT(1) INTO tableexists FROM all_tab_columns WHERE OWNER = (SELECT USER FROM DUAL) AND table_name = curTableName;

  --If current month's count table exists, drop it
  IF tableexists > 0 THEN
    EXECUTE IMMEDIATE 'DROP TABLE '||curTableName;
  END IF;

  --Create current month's count table
  EXECUTE IMMEDIATE '
  CREATE TABLE '||curTableName||' AS (
    SELECT * FROM (
      SELECT movetype, phone_flag, state FROM countpull
      )
    PIVOT (
      COUNT(state)
      FOR state IN ('''||'AA'||''','''||'AE'||''','''||'AK'||''','''||'AL'||'''
        ,'''||'AP'||''','''||'AR'||''','''||'AS'||''','''||'AZ'||''','''||'CA'||'''
        ,'''||'CO'||''','''||'CT'||''','''||'DC'||''','''||'DE'||''','''||'FL'||'''
        ,'''||'FM'||''','''||'GA'||''','''||'GU'||''','''||'HI'||''','''||'IA'||'''
        ,'''||'ID'||''','''||'IL'||''','''||'IN'||''','''||'KS'||''','''||'KY'||'''
        ,'''||'LA'||''','''||'MA'||''','''||'MD'||''','''||'ME'||''','''||'MH'||'''
        ,'''||'MI'||''','''||'MN'||''','''||'MO'||''','''||'MP'||''','''||'MS'||'''
        ,'''||'MT'||''','''||'NC'||''','''||'ND'||''','''||'NE'||''','''||'NH'||'''
        ,'''||'NJ'||''','''||'NM'||''','''||'NV'||''','''||'NY'||''','''||'OH'||'''
        ,'''||'OK'||''','''||'OR'||''','''||'PA'||''','''||'PR'||''','''||'PW'||'''
        ,'''||'RI'||''','''||'SC'||''','''||'SD'||''','''||'TN'||''','''||'TX'||'''
        ,'''||'UT'||''','''||'VA'||''','''||'VI'||''','''||'VT'||''','''||'WA'||'''
        ,'''||'WI'||''','''||'WV'||''','''||'WY'||''')
    ))';

END;

当我不尝试使用变量作为表名时,上面的脚本工作得很好。但是由于我希望每次运行脚本时都动态更改表名,因此我想避免使用静态名称。

为什么在 PL/SQL 块中创建具有动态表名的表无效?

附加信息:

countpull 的表模式是

state NVARCHAR2(2),
movetype NVARCHAR2(1),
phone_flag NVARCHAR2(1)
4

1 回答 1

2

由于我不清楚的原因,问题是您使用的变量是nvarchar2. 如果您将其声明为varchar2

  curTableName VARCHAR2(50);

通过SQL Fiddle验证;如果您只是将表名变量的声明更改为nvarchar2.

正如@jonearles 指出的那样,文档确实声明命令字符串的“类型必须是CHAR,VARCHAR2CLOB'。虽然连接运算符的文档没有提到它,但相关concat函数确实声明“如果参数之一是国家数据类型,则返回的值是国家数据类型” - 所以你的命令字符串是nvarchar2因为您在连接中使用的变量是nvarchar2,使execute immediate语句的参数非法。

不过,动态创建表格并不是一个好主意。Schema 对象通常应该创建一次。你可以有一个表 - 可能是一个全局临时表 - 有一个月份列,或者在推送十二个表时,你可以根据需要清空和填充。

此外,您的所有select from dual陈述都可以简化:

  curMonthChar := TO_CHAR(ADD_MONTHS(sysdate,-1),'fmMONTH');
  curTableName := 'QP17414_'||curMonthChar);

等等,即使在您的子查询中:

... WHERE OWNER = user AND ...

...而且我不知道您为什么在枢轴子句中使用如此多的连接。

于 2013-10-15T22:44:35.453 回答