在 PL/SQL 中添加带有布尔值的新列

Add new column with Boolean in PL/SQL

我正在学习 PL/SQL,但我有疑问。 我创建了以下名为 tbProducts 的 table:

CREATE TABLE tbProducts (
                        nIDProduct NUMBER(2) NOT NULL,
                        vDescription VARCHAR2(20 CHAR),
                        nQuantity NUMBER(3),
                        nPrice NUMBER(6,2),
                        dLastDate DATE)

我插入了一些值,所以 table 是这样的:

nIDProduct | vDescription | nQuantity | nPrice | dLastDate
         1 |     'Hammer' |        50 |   3.25 | 13-MAY-2021
         2 |      'Nails' |       100 |   0.75 | 28-AUG-2021
         3 |     'Screws' |       250 |   0.16 | 21-JUL-2021

现在我要找的是一个可以称为 bUpdate 的布尔变量,如果今天的日期(2021 年 8 月 26 日)大于 dLastDate,则 returns FALSE,如果是 returns TRUE,则它小于或等于,所以 table 看起来像这样:

nIDProduct | vDescription | nQuantity | nPrice | dLastDate   | bUpdate
         1 |     'Hammer' |        50 |   3.25 | 13-MAY-2021 | FALSE
         2 |      'Nails' |       100 |   0.75 | 28-AUG-2021 | TRUE
         3 |     'Screws' |       250 |   0.16 | 21-JUL-2021 | FALSE

我正在尝试执行以下操作:

DECLARE
     bUpdate BOOLEAN;

BEGIN
     
     SELECT t.*, bUpdate(
                        IF SYSDATE > dLastDate THEN
                               bUpdate := FALSE;
                        ELSE
                               bUpdate := TRUE;
                        END IF
         FROM tbProducts t
         ;
END;

我收到一条错误消息,指出在 SELECT 语句之后需要一个 FROM。 由于我还在学习,我不知道这个声明有什么问题,有人可以帮助我吗?有没有办法用 CURSOR 来做呢? 谢谢大家!

你的尝试是行不通的。如果您想要一个额外的列,您需要使用 ALTER TABLE 命令将该列添加到 table - 但在这种情况下,您添加的是一个不确定的表达式,并且不能作为虚拟表达式添加列。

实现您想要的效果的最简单方法是使用 case 语句在 table 之上创建一个视图,如下所示:

CREATE TABLE tbproducts (
                        nidproduct NUMBER(2) NOT NULL,
                        vdescription VARCHAR2(20 CHAR),
                        nquantity NUMBER(3),
                        nprice NUMBER(6,2),
                        dlastdate DATE);

INSERT INTO tbproducts (nidproduct,vdescription,nquantity,nprice,dlastdate) VALUES (1,'Hammer', 50,3.25,TO_DATE('13-MAY-2021','DD-MON-YYYY'));
INSERT INTO tbproducts (nidproduct,vdescription,nquantity,nprice,dlastdate) VALUES (2, 'Nails',100,0.75,TO_DATE('28-AUG-2021','DD-MON-YYYY'));
INSERT INTO tbproducts (nidproduct,vdescription,nquantity,nprice,dlastdate) VALUES (3,'Screws',250,0.16,TO_DATE('21-JUL-2021','DD-MON-YYYY'));  

CREATE VIEW tbproducts_v
AS
SELECT 
  nidproduct
 ,vdescription
 ,nquantity
 ,nprice
 ,dlastdate
 ,CASE WHEN SYSDATE > dlastdate THEN 'TRUE' ELSE 'FALSE' END as status
FROM  tbproducts;

select * from tbproducts_v;

NIDPRODUCT VDESCRIPTION          NQUANTITY     NPRICE DLASTDATE   STATU
---------- -------------------- ---------- ---------- ----------- -----
         1 Hammer                       50       3.25 13-MAY-2021 TRUE 
         2 Nails                       100        .75 28-AUG-2021 FALSE
         3 Screws                      250        .16 21-JUL-2021 TRUE 

如果您坚持要添加一个新列,那么这就是您要做的。

ALTER TABLE tbproducts ADD status VARCHAR2(100);

UPDATE tbproducts t 
   SET (t.status) = 
      (SELECT 
        CASE WHEN SYSDATE > dlastdate THEN 'TRUE' ELSE 'FALSE' END 
         FROM tbproducts st 
        WHERE st.nidproduct = t.nidproduct);

如果你只想在控制台中用 pl/sql 块显示 true/false 那么这是一个选项(使用隐式游标循环):

set serveroutput on size 999999
clear screen
DECLARE
BEGIN
  FOR r IN (SELECT * FROM tbproducts) LOOP
    dbms_output.put_line('Product '||r.vdescription ||', status: '||CASE WHEN SYSDATE > r.dlastdate THEN 'TRUE' ELSE 'FALSE' END);
    IF r.dlastdate < SYSDATE THEN
      dbms_output.put_line('Product '||r.vdescription ||' is expired !');
    END IF;
  END LOOP;

END;
/

注 1:pl/sql 有布尔数据类型,但 sql 没有。所以在你的 table 中你需要存储一个字符串 (1/0, T/F, Y/N, TRUE/FALSE).

注意 2:在 table 名称或列名称中使用驼峰式命名不是一个好习惯。如果您在不使用引号的情况下创建它们,那么名称无论如何都不区分大小写。