【问题标题】:Excute SELECT after CREATE in Oracle PL/SQL在 Oracle PL/SQL 中 CREATE 之后执行 SELECT
【发布时间】:2015-11-02 01:48:34
【问题描述】:

我是 Oracle PL/SQL 的新手,虽然我对 SQL 有很多经验。 目前我正在尝试将几个 T-SQL 语句转换为 PL/SQL。我正在尝试执行以下代码,但出现了一些错误。

如果表还不存在,则错误为:表或视图不存在。 但是当我在没有第二个 select 语句的情况下运行查询时,它会创建表。现在该表存在,我尝试再次执行它,现在我收到以下错误:

在这个 SELECT 语句中需要一个 INTO 子句。

我正在使用的代码:

DECLARE
  cnt NUMBER;
  stmt VARCHAR2(1000) := 'CREATE TABLE LAST_LOG_ARCHIVE (LAST_LOG_ARCHIVE TIMESTAMP NULL)';
BEGIN
    SELECT COUNT(*) INTO cnt FROM all_tables WHERE table_name = 'LAST_LOG_ARCHIVE';

    IF (cnt = 0) THEN
        EXECUTE IMMEDIATE stmt;
    END IF;

    SELECT COALESCE((
      SELECT LAST_LOG_ARCHIVE FROM LAST_LOG_ARCHIVE WHERE ROWNUM = 1
      ), TO_TIMESTAMP('2015-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')) AS LAST_LOG_ARCHIVE FROM dual;
END;

我该如何解决这个问题...?

【问题讨论】:

  • 嗯,是的,您的第二个选择正在返回一个值,而您没有对它做任何事情。您想对重新调整的 LAST_LOG_ARCHIVE 做什么?只需执行与“select count(*) into”相同的操作,您的代码就可以工作,然后您可以决定如何处理该值。
  • Coalesce 函数首先返回非空值,因此为了在 oracle 中保存该值,我们需要一个变量,如 select coalesce(var1,var2) into var3 from table _name。现在 var3 包含 var1 或 var2。
  • 当表不存在时,预编译器会看到您在第二次选择中引用了一个在编译时不存在的对象 (LAST_LOG_ARCHIVE)
  • @Robert:我明白这一点。因此,我尝试检查表是否存在,如果不存在则创建它。
  • @user2782991 如果表不存在,PL/SQL 编译器看不到您将创建该表。在编译时,您引用的表不存在并且总是会返回编译器错误。如果你想这样做,你也必须将选择转换为动态 sql。

标签: sql oracle plsql select-into


【解决方案1】:

您的第二个查询需要 INTO 语句

SELECT COALESCE((
      SELECT LAST_LOG_ARCHIVE FROM LAST_LOG_ARCHIVE WHERE ROWNUM = 1
      ), TO_TIMESTAMP('2015-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')) AS LAST_LOG_ARCHIVE 
INTO l_someVariable 
FROM dual;

记得在DECLARE 部分声明l_someVariable

【讨论】:

    【解决方案2】:

    变化:

    DECLARE
      cnt NUMBER;
      stmt VARCHAR2(1000) := 'CREATE TABLE LAST_LOG_ARCHIVE (LAST_LOG_ARCHIVE TIMESTAMP NULL)';
    BEGIN
        SELECT COUNT(*) INTO cnt FROM all_tables WHERE table_name = 'LAST_LOG_ARCHIVE';
    
    IF (cnt = 0) THEN
        EXECUTE IMMEDIATE stmt;
    END IF;
    
    SELECT COALESCE((
      SELECT LAST_LOG_ARCHIVE FROM LAST_LOG_ARCHIVE WHERE ROWNUM = 1
      ), TO_TIMESTAMP('2015-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')) AS LAST_LOG_ARCHIVE FROM dual;
    END;
    

    收件人:

    DECLARE
      V_LAST_LOG_ARCHIVE varchar2(100);
      cnt NUMBER;
      stmt VARCHAR2(1000) := 'CREATE TABLE LAST_LOG_ARCHIVE (LAST_LOG_ARCHIVE TIMESTAMP NULL)';
    BEGIN
        SELECT COUNT(*) INTO cnt FROM all_tables WHERE table_name = 'LAST_LOG_ARCHIVE';
    
    IF (cnt = 0) THEN
        EXECUTE IMMEDIATE stmt;
    END IF;
    
    SELECT COALESCE((
      SELECT LAST_LOG_ARCHIVE 
        FROM LAST_LOG_ARCHIVE 
       WHERE ROWNUM = 1), TO_TIMESTAMP('2015-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')) 
        INTO V_LAST_LOG_ARCHIVE 
        FROM dual;
    END;
    

    【讨论】:

    • 程序现在执行,但是如何从那个变量中得到结果呢?我尝试使用 dbms_output.put_line(V_LAST_LOG_ARCHIVE)。不幸的是没有成功......实际上它需要在一个 .NET 应用程序中结束。
    • 你现在拥有的只是一个匿名块,而不是一个过程。您想在第一行中输入:“创建或替换过程 PROCEDURE_NAME (v_out_LAST_LOG_ARCHIVE as varchar2) AS”。然后在最后添加另一个“结束”;陈述。现在,这将构建程序,当您添加“return V_LAST_LOG_ARCHIVE”行时,该程序将返回您选择的变量。我不知道 PLSQL 过程调用如何在 .NET 中工作。此外,如果您希望 dbms_output.put_line 工作,您需要“设置 serveroutput on;”在您的终端或您正在使用的任何工具中。
    【解决方案3】:

    选择合并(( 从 LAST_LOG_ARCHIVE 中选择 LAST_LOG_ARCHIVE,其中 ROWNUM = 1 ), TO_TIMESTAMP('2015-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')) AS LAST_LOG_ARCHIVE FROM dual;

    PL/SQLSQL 不同。您必须使用 INTO 子句,因为没有 INTO 子句的 SELECT 语句在 PL/SQL 中会失败。基本上,选择一行而不做任何事情是没有意义的。

    如果您只想进行选择,请在纯 SQL 中进行,而不是在 PL/SQL 中进行。如果要将 select 返回的行中的相应值存储到局部变量中,请使用 INTO 子句。

    SELECT col1, col2 INTO var1, var2 FROM table
    

    用选择列表中各列的数据类型声明变量var1var2

    从文档中了解更多关于 SELECT INTO Statement 的信息。

    还有,

    TO_TIMESTAMP('2015-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'))

    您可以简单地使用 TO_DATE 而不是 TO_TIMESTAMP。 Date 包含日期和时间元素。

    TO_DATE('2015-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多