【问题标题】:SQL: Stored procedureSQL:存储过程
【发布时间】:2016-12-19 04:47:47
【问题描述】:

我正在用 SQL 实现一个图书馆管理系统。我有以下表结构和一些插入其中的值:

create table books
(
IdBook number(5),
NameBook varchar2(35),
primary key(IdBook)
);

create table users
(
IdUsers number(5),
NameUser varchar2(20),
primary key(IdUsers)
);

create table borrowed
(
IdBorrowed number(5),
IdUsers number(5),
IdBook number(5),
DueDate date,
DateReturned date,
constraint fk_borrowed foreign key(IdUsers) references users(IdUsers),
constraint fk_borrowed2 foreign key(IdBook) references books(IdBook)
);

insert into books values(0,'FairyTale');
insert into books values(1,'Crime and Punishment');
insert into books values(2,'Anna Karenina');
insert into books values(3,'Norwegian Wood');

insert into users values(01,'Robb Dora');
insert into users values(02,'Pop Alina');
insert into users values(03,'Grozavescu Teodor');
insert into users values(04,'Popa Alin');

insert into borrowed values(10,02,3,'22-Jan-2017',null);
insert into borrowed values(11,01,1,'25-Jan-2017','19-Dec-2016');
insert into borrowed values(12,01,3,'22-Jan-2017',null);
insert into borrowed values(13,04,2,'22-Jan-2017','13-Dec-2016');

我现在想要的是我的数据库允许为没有未归还的书籍(即返回的日期不为空)的用户“借阅”书籍(即插入到借来的表中),如果他们有未归还的书籍我想要放弃整个过程。我想通过以下方式实现这一点:

create or replace procedure borrowBook(IdBorrowed in number,IdUsers number,IdBook number,DueDate date,DateReturned date) as begin
if exists (SELECT u.IdUsers, u.NameUser, b.DateReturned
        FROM users u, borrowed b
        WHERE  u.IDUSERS = b.IdUsers and DateReturned is not null),
insert into borrowed values(IdBorrowed,IdUsers,IdBook,DueDate,DateReturned);
end borrowBook;

上述过程不检查我传递给这个函数的参数是否与我的选择中的参数相同,我不知道如何做到这一点并在我的表中正确插入一个值。

任何帮助将不胜感激。提前致谢!

【问题讨论】:

    标签: sql oracle stored-procedures plsql sql-insert


    【解决方案1】:

    您不应将参数命名为与过程中也使用的列相同的名称。

    您还可以将过程简化为单个 INSERT 语句,不需要 IF

    create or replace procedure borrowBook(p_idborrowed in number, p_idusers number, p_idbook number, p_duedate date, p_datereturned date) 
    as 
    begin
    
      insert into borrowed (idborrowed, idusers, idbook, duedate, datereturned)
      select p_idborrowed, p_idusers, p_idbook, p_duedate, p_datereturned
      from dual
      where not exists (select * 
                        from users u
                          join borrowed b on u.idusers = b.idusers
                        and b.datereturned is not null);
    
    end borrowBook;
    

    明确列出INSERT 语句的列也是一种很好的编码风格。你应该习惯显式的JOIN 操作符,而不是在where 子句中使用隐式连接。

    【讨论】:

      【解决方案2】:

      这个呢:

      create or replace procedure borrowBook( p_IdBorrowed  in number   ,
                                              p_IdUsers        number   ,
                                              p_IdBook         number   ,
                                              p_DueDate        date     ,
                                              p_DateReturned   date        ) 
      as 
      begin
          if (SELECT COUNT(*) 
                FROM borrowed
               WHERE  IDUSERS = p_IdUsers 
                 AND DateReturned IS NULL) = 0 THEN
      
              insert into borrowed values (p_IdBorrowed   ,
                                           p_IdUsers      , 
                                           p_IdBook       , 
                                           p_DueDate      ,
                                           p_DateReturned   );
          end if ;
      end borrowBook;
      

      【讨论】:

        【解决方案3】:

        你似乎想要这样的东西:

        create or replace procedure borrowBook (
            in_IdBorrowed in number,
            in_IdUsers number,
            in_IdBook number,
            in_DueDate date,
            in_DateReturned date
        ) as
            v_flag number;
        begin
            select (case when exists (select 1
                                      from borrowed b
                                      where b.IdUsers = in_IdUsers and b.DateReturned is not null
                                     )
                         then 1 else 0
                    end)
            into v_flag
            from dual;
        
            if (flag = 0) then
                insert into borrowed     
                    values(in_IdBorrowed, in_IdUsers, in_IdBook, in_DueDate, v_DateReturned);
            end if
        end -- borrowBook;
        

        【讨论】:

        • 如果我尝试运行它,我会收到以下错误:错误(10,5):PL/SQL:SQL 语句被忽略错误(12,49):PL/SQL:ORA-00904:“ IN_IDUSER":无效标识符错误(20,9):PL/SQL:SQL 语句被忽略错误(21,70):PL/SQL:ORA-00984:此处不允许列
        • @didi 。 . .这就是所谓的“错字”。
        猜你喜欢
        • 2012-07-12
        • 2018-05-08
        • 2011-10-12
        • 2011-08-03
        • 1970-01-01
        • 2021-12-11
        相关资源
        最近更新 更多