回答

收藏

PostgreSQL约束和断言

技术问答 技术问答 463 人阅读 | 0 人回复 | 2023-09-14

我试图创建一个简单的数据库,包括一个客户数据表和一个订单数据表。我试图写一个约束,这样客户就不能在给定的一天订购超过特定数量的商品。这就是我所拥有的:
- O$ x: W) r2 ?( YCREATE TABLE CUSTOMER(    CUSTOMER_NUM CHAR(3) PRIMARY KEY,   CUSTOMER_NAME CHAR(35) NOT NULL,   STREET CHAR(15),   CITY CHAR(15),   STATE CHAR(3),   ZIP CHAR(5),);CREATE TABLE ORDERS(    ORDER_NUM CHAR(5) PRIMARY KEY,   ORDER_DATE DATE,   CUSTOMER_NUM CHAR(3),   CONSTRAINT CUSTOMER_NUM_FKEY FOREIGN KEY (CUSTOMER_NUM)        REFRENCES CUSTOMER (CUSTOMER_NUM) MATCH SIMPLE        ON UPDATE CASCADE ON DELETE CASCADE );这是我为强制执行这种约束而写的,但它不起作用。我认为这是因为ORDER_NUM和ORDER_DATE永远不会有等值。7 V7 r$ Q' n$ U
CREATE ASSERTION ITEM_LIMITCEHCK(       (  )SELECT COUNT(*)            FROM CUSTOMER C1,ORDERS O                                                                                                                                                                                                                                                                                                                                  WHERE C1.CUSTOMER_NUM = O1.CUSTOMER_NUM AND                O1.ORDER_DATE = O1.ORDER_NUM     ) 我的问题是如何使这种约束发挥作用,比如如何限制每天的订单量。7 g, z" c, C/ \+ o& y3 e. J
                                                                8 M; G2 a- Z, p5 J" T; ]1 D
    解决方案:                                                                % I! |2 _2 v4 }  w5 O
                                                                由于@ruakh所以已经清除了CREATEASSERTIONPostgreSQL中没有。只需检查SQL命令列表可以。不在那里。, ]  b( |6 p8 E! |4 j
可以用触发器结合CHECK限制更新每个客户的计数,但您必须涵盖所有相关的计数DML语句:INSERT,UPDATE,DELETE。可能看起来像这样:
  w/ Q+ l3 S, F, p$ U" \; N3 O! |准备现有客户表:
& N2 K8 p, z7 pALTER TABLE customer ADD COLUMN order_ct integer DEFAULT 0;UPDATE customer SET order_ct = 0;ALTER TABLE customer ALTER order_ct SET NOT NULL;ALTER TABLE customer ADD CONSTRAINT order_ct_max1000 CHECK (order_ct 创建触发器函数和触发器:% B! G; \- {' G- _% n( d6 C
CREATE OR REPLACE FUNCTION trg_order_upaft()  RETURNS trigger AS$BODY$BEGINIF OLD.customer_num  NEW.customer_num THEN    UPDATE customer    SET    order_ct = order_ct - 1    WHERE  customer_num = OLD.customer_num;    UPDATE customer    SET    order_ct = order_ct   1    WHERE  customer_num = NEW.customer_num;END IF;RETURN NULL;END;$BODY$  LANGUAGE plpgsql;CREATE TRIGGER upaft  AFTER UPDATE ON orders FOR EACH ROW  EXECUTE PROCEDURE trg_order_upaft();CREATE OR REPLACE FUNCTION trg_order_insaft()  RETURNS trigger AS$BODY$BEGINUPDATE customerSET    order_ct = order_ct   1WHERE  customer_num = NEW.customer_num;RETURN NULL;END;$BODY$  LANGUAGE plpgsql;CREATE TRIGGER insaft  AFTER INSERT ON orders FOR EACH ROW  EXECUTE PROCEDURE trg_order_insaft();CREATE OR REPLACE FUNCTION trg_order_delaft()  RETURNS trigger AS$BODY$BEGINUPDATE customerSET    order_ct = order_ct - 1;WHERE  customer_num = OLD.customer_num;RETURN NULL;END;$BODY$  LANGUAGE plpgsql;CREATE TRIGGER delaft  AFTER DELETE ON orders FOR EACH ROW  EXECUTE PROCEDURE trg_order_delaft();我在触发器之后做了所有这些触发器-这就是为什么可以。RETURNNULL。在这种情况下,后比前更可取。如果任何其他条件都可以取消中间条件DML句子(如其他触发器)效果会更好。6 m) {1 |! [: {& N
如果一无所获,最好用BEFORE触发器。在这种情况下,请确保触发功能相应返回NEW / OLD。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则