【问题标题】:Create a procedure to print the result of and SQL query创建一个过程来打印 SQL 查询的结果
【发布时间】:2018-03-24 00:09:57
【问题描述】:

我正在使用 Oracle SQL 开发人员,我想创建一个过程来打印此 SQL 代码的结果:

SELECT Title , Name  
FROM BOOK, BORROWER, BOOK_LOANS
WHERE Due_date = SYSDATE AND Return_date = NULL;

这是我的代码。我不断收到“忽略 SQL 语句,忽略语句,LOOP 索引变量 'books' 无效”。请告诉我我在这里缺少什么。我尝试将 SQL 语句移动到游标,但它也不起作用。

CREATE OR REPLACE PROCEDURE overdueToday IS   
BEGIN
    FOR books IN (SELECT Title , Name  
                  FROM BOOK, BORROWER, BOOK_LOANS
                  WHERE Due_date = SYSDATE 
                    AND Return_date = NULL)
    LOOP
        DBMS_OUTPUT.put_line(books.Title || ' -- ' || books.Name);
    END LOOP;
END overdueToday;
/

【问题讨论】:

  • 您的查询不正确。您正在引用三个表,其中没有以任何方式连接。因此,除非您打算进行交叉连接,否则这是首先要解决的问题。
  • 请给出使用 BOOK、BORROWER、BOOK_LOANS 的表模式
  • 请检查我的回答,如果有帮助请告诉我。另外,请阅读:stackoverflow.com/help/someone-answers

标签: oracle plsql


【解决方案1】:

除了你已经被告知(交叉加入)之外,WHERE 条件将不起作用。 SYSDATE 是一个返回日期和时间的函数,所以它不可能返回任何东西。你应该使用TRUNC函数。

此外,在处理 NULL 值时,它们不“等于” (=) 任何东西 - 您应该使用 IS NULL(或 IS NOT NULL,具体取决于您的操作)。

下面的例子有点愚蠢;你没有提供测试用例,所以我用绝对最小的列集创建自己的表,只是为了确保过程不会失败。

SQL> create table book (title varchar2(20));

Table created.

SQL> create table borrower (name varchar2(20));

Table created.

SQL> create table book_loans (due_date date, return_date date);

Table created.

SQL>
SQL> insert into book values ('Pinky');

1 row created.

SQL> insert into borrower values ('Littlefoot');

1 row created.

SQL> insert into book_loans values (trunc(sysdate), null);

1 row created.

SQL>

程序;我标记了你应该注意的地方:

SQL> set serveroutput on;
SQL> create or replace procedure overduetoday
  2    is
  3  begin
  4    for books in ( select title,
  5                          name
  6                   from book,
  7                        borrower,
  8                        book_loans
  9                   where due_date = trunc(sysdate)   --> trunc!
 10                     and return_date is null         --> is!
 11    ) loop
 12      dbms_output.put_line(books.title ||' -- '|| books.name);
 13    end loop;
 14  end overduetoday;
 15  /

Procedure created.

SQL>
SQL> exec overduetoday;
Pinky -- Littlefoot

PL/SQL procedure successfully completed.

SQL>

如您所见,它有效(或者,我应该说,*不会失败”。如果这些表中有更多行,结果将是错误的)。

您发布的代码不会引发您提到的错误。这就是为什么像我一样发布准确你所做的事情很重要。这样做,毫无疑问你拥有什么、你做了什么以及甲骨文如何回应。其他一切都只是猜测。

【讨论】:

    【解决方案2】:

    Oracle 12c 及以上版本,您可以使用DBMS_SQL.RETURN_RESULT。您在查询中需要适当的连接条件和别名,我们不知道。

    CREATE OR replace PROCEDURE OverdueToday
    IS
      rc SYS_REFCURSOR;
    BEGIN
        OPEN rc FOR
          SELECT title,  --  b.title ?
                 name    --  br.name ?
          FROM   book b
                 join borrower br
                   ON ( 1 = 1 ) --Add proper join condition here
                 join book_loans bl
                   ON ( 1 = 1 ) --Add proper join condition here
          WHERE  due_date = TRUNC(SYSDATE)
                 AND return_date IS NULL;
    
        DBMS_SQL.RETURN_RESULT(rc);
    END overduetoday;
    
    /  
    

    【讨论】:

      【解决方案3】:

      如果您使用的是 SQL Developer,则只需运行查询(按 F5Ctrl+Enter)。您无需编写 PL/SQL 程序。

      话虽如此,您的查询几乎可以肯定是错误的,因为您有三个表并且它们没有连接条件。但是你仍然应该得到一些输出。

      【讨论】:

        【解决方案4】:

        这是在 select 语句中循环的简单方法:

           CREATE OR REPLACE PROCEDURE overdueToday IS  
                    CURSOR book_cur is 
                       SELECT Title , Name  
                    FROM BOOK, BORROWER, BOOK_LOANS
                      WHERE Due_date = SYSDATE 
                      AND Return_date = NULL;
        
                BEGIN
                    FOR book_rec IN book_cur loop                
                        DBMS_OUTPUT.put_line(book_rec .Title || ' -- ' || book_rec .Name);
                    END LOOP;
                END overdueToday;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-05-23
          • 1970-01-01
          • 2013-09-28
          • 2012-08-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-28
          相关资源
          最近更新 更多