【问题标题】:Create Table As within PL/SQL?在 PL/SQL 中创建表?
【发布时间】:2012-03-24 03:03:40
【问题描述】:

我正在尝试在 PL/SQL 中创建一个表

我怎样才能做到这一点?

继续获得

错误报告:

ORA-00933:“SQL 命令未正确结束”

这是我有错误的代码

DECLARE
  station_id_ms1  NUMBER :=10347;
  realtime_start  DATE   :=to_date('2012-01-01 00:00:00','YYYY-DD-MM HH24:MI:SS');
  realtime_end    DATE   :=to_date('2012-07-01 00:00:00','YYYY-DD-MM HH24:MI:SS');
BEGIN
  EXECUTE IMMEDIATE ('
  CREATE TABLE new_table_name
  AS
  SELECT
  ((realtime - to_date(''01-JAN-1970'',''DD-MON-YYYY'')) * (86400)) AS realtime_ms1,
  magnetic_ms_id,
  ADC_value_pp_2_mgntc_fld_amp(ch2_value,ch2_gain_value,magnetic_ms_id,2) AS B_x_ms1,
  ADC_value_pp_2_mgntc_fld_amp(ch1_value,ch1_gain_value,magnetic_ms_id,1) AS B_y_ms1,
  real_nanosecs2*4/3*360/20e6 AS phase_x_ms1,
  real_nanosecs1*4/3*360/20e6 AS phase_y_ms1
  FROM
      raw_mag
  WHERE
    magnetic_ms_id    = '||station_id_ms1||'
  AND realtime        > '||realtime_start||'
  AND realtime        < '||realtime_end||'
  AND ch1_tune_value  = 0
  AND realtime        < pkg_timezone.change_timezone(gettime,''CET'',''UTC'')
  ');  
END;

【问题讨论】:

  • 为什么是EXECUTE IMMEDIATE?只需创建表。
  • @vulkanino:因为如果没有 EXECUTE IMMEDIATE 就无法在 PL/SQL 中执行 DDL 语句。
  • @Benoit - 这只是提出了问题。为什么选择 PL/SQL?为什么不直接创建表?在某些情况下它是合法的,但这种方法被误导或完全错误的情况远远超过它们。
  • @APC - 你是什么意思? “创建表”似乎在 PL/SQL 下不起作用!你有一个例子表明它有效吗? ....谢谢
  • @Data-Base - 我的意思是,数据库模式应该是稳定的。我们希望像表格这样的东西会慢慢改变,因此使用 DDL 脚本创建,最好是在源代码控制下的脚本。在 PL/SQL 中创建表的要求不适合该模型。现在也许确实需要在后台作业中动态创建表。但更常见的原因是开发人员误解了需求和/或不知道如何编写合适的 Oracle 数据库应用程序。

标签: oracle plsql oracle11g


【解决方案1】:

您应该在您立即执行的 plsql 字符串中进行 char-to-date 转换。

您声明的日期将在连接中“反向转换”到 varchar2 并再次“重新转换”到日期以执行 create table 语句。在这两种类型转换中可能会发生“各种各样的事情”,因此您要确保在转换为日期时可以控制字符串的解释方式。

DECLARE
  station_id_ms1  NUMBER :=10347;
  realtime_start  VARCHAR2(100)   :='2012-01-01 00:00:00';
  realtime_end    VARCHAR2(100)   :='2012-07-01 00:00:00';
BEGIN
  EXECUTE IMMEDIATE ('
  CREATE TABLE new_table_name
  AS
  SELECT
  ((realtime - to_date(''01-JAN-1970'',''DD-MON-YYYY'')) * (86400)) AS realtime_ms1,
  magnetic_ms_id,
  ADC_value_pp_2_mgntc_fld_amp(ch2_value,ch2_gain_value,magnetic_ms_id,2) AS B_x_ms1,
  ADC_value_pp_2_mgntc_fld_amp(ch1_value,ch1_gain_value,magnetic_ms_id,1) AS B_y_ms1,
  real_nanosecs2*4/3*360/20e6 AS phase_x_ms1,
  real_nanosecs1*4/3*360/20e6 AS phase_y_ms1
  FROM
      raw_mag
  WHERE
    magnetic_ms_id    = '||station_id_ms1||'
  AND realtime        > to_date(''' || realtime_start || ''', ''YYYY-DD-MM HH24:MI:SS'')
  AND realtime        < to_date(''' || realtime_end   || ''', ''YYYY-DD-MM HH24:MI:SS'')
  AND ch1_tune_value  = 0
  AND realtime        < pkg_timezone.change_timezone(gettime,''CET'',''UTC'')
  ');  
END;

【讨论】:

    【解决方案2】:

    我会为 station_id_ms1、realtime_start、realtime_end 使用绑定:

    EXECUTE IMMEDIATE '
     ...
     WHERE
     magnetic_ms_id    = :station_id_ms1
      AND realtime        > :realtime_start
      AND realtime        < :realtime_end
     ...
     ' USING IN station_id_ms1, realtime_start, realtime_end
    

    【讨论】:

    • 你的意思是在 station_id_ms1、realtime_start、realtime_end 中使用 ???如果是这样,那么我会收到此错误 ORA-00936: "missing expression"
    • 是的,绑定。查询中的这个值 :station_id_ms1 将自然地替换为 USING IN station_id_ms1 中写入的值。
    • 我得到了这个 ORA-01027:“数据定义操作不允许绑定变量”
    • 发现此“在 DML 语句(SELECT、UPDATE、DELETE)或程序内部允许绑定变量,但在 DDL(数据定义语言语句)内部不允许绑定变量”
    • 啊,在这种情况下,您应该更加小心地处理日期变量。在查询中应该出现 to_date(variable, format)。声明是文本。日期变量将作为 varchar2(隐式转换)