簡體   English   中英

無需重新插入即可更新行的正確 PL/SQL 是什么?

[英]What is the right PL/SQL for updating rows without a need to reinsert it?

我是使用 PL/SQL 的新手,我想要以下內容:我在 Oracle SQLcl 上有這張表

create table Child (
id varchar not null,
name varchar not null,
gender varchar not null,
YearOfBirth number(4) not null,
YearsOfAge number(4) null,

CONSTRAINT Pk primary key (id)

);

我想要一個 PL/SQL(首選匿名),通過從“YearOfBirth”字段中減去 2020 來更新“YearsOfAge”字段。 我可以這樣做,但我的問題是在我再次插入 PL/SQL 塊之前不會更新表。 所以每當我插入一個新行時,我必須再次插入我的 PL/SQL 塊。 我想在插入/更新一行時更新表,而不需要在新行之后插入這個塊。

更清楚地說,我只想在創建表后插入一次 SL/SQL 塊,然后每當我插入/更新/刪除一行時更新表的“YearsOfAge”。 所以當我寫“select * from Child;”時我需要查看“YearsOfAge”以及從“YearOf Birth”中減去 2020 計算得出的新值。 我當前的 PL/SQL 如下:

begin
IF INSERTING THEN
update Child set YearsOfAge = 2020 - YearOfBirth;
ELSIF DELETEING THEN
update Child set YearsOfAge = 2020 - YearOfBirth;
ELSE
update Child set YearsOfAge = 2020 - YearOfBirth;
END IF;
END;
/

如果你真的需要以這種方式存儲年齡,一些選項是虛擬列、視圖和觸發器。

虛擬列

使用虛擬列,Oracle 將自動執行計算。

SQL> create table Child
  2  (
  3      id          number not null,
  4      name        varchar2(10) not null,
  5      gender      varchar2(10) not null,
  6      YearOfBirth number(4) not null,
  7      YearsOfAge  number generated always as (2020 - yearOfBirth) null,
  8      constraint pk_child primary key (id)
  9  );

Table created.

SQL> insert into child(id, name, gender, yearOfBirth) values(1, 'A', 'female'    , 1990);

1 row created.

SQL> insert into child(id, name, gender, yearOfBirth) values(2, 'B', 'male'      , 2000);

1 row created.

SQL> insert into child(id, name, gender, yearOfBirth) values(3, 'C', 'non-binary', 2010);

1 row created.

SQL> select * from child;

        ID NAME       GENDER     YEAROFBIRTH YEARSOFAGE
---------- ---------- ---------- ----------- ----------
         1 A          female            1990         30
         2 B          male              2000         20
         3 C          non-binary        2010         10

看法

虛擬列的一個缺點是它們不能使用像SYSDATE這樣的函數,因此必須對年份進行硬編碼。 使用視圖,表達式可以引用SYSDATE並且始終是最新的:

create or replace view child_view as
select id, name, gender, yearOfBirth, extract(year from sysdate) - yearOfBirth yearsOfAge
from child;

觸發(警告)

您還可以使用觸發器在插入或更新行時創建值:

create or replace trigger child_trg
before update or insert on child
for each row
begin
    if updating('YEAROFBIRTH') or inserting then
        :new.yearsOfAge := extract(year from sysdate) - :new.yearOfBirth;
    end if;
end;
/   

但在實踐中,觸發器很難維持。 這就引出了一個問題:你為什么要首先存儲這些信息?

良好的數據庫設計應盡量減少冗余數據量。 總是有例外,但你應該有一個很好的理由來處理這些例外,比如你不希望別人出錯的特別復雜的計算,由於不尋常的安全約束,你不能創建 PL/SQL function 等. 計算年齡這樣微不足道的事情可能會導致比它解決的問題更多的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM