当前位置: 首页 > 面试题库 >

PostgreSQL中的约束和断言

鄢博简
2023-03-14
问题内容

我正在尝试创建一个简单的数据库,其中有一张客户数据表和一张订单数据表。我正在尝试写一个约束,使客户在给定的一天不能订购超过特定数量的商品。这是我所拥有的:

CREATE 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永远不会有相等的值。

CREATE ASSERTION ITEM_LIMIT
CEHCK(
        (   SELECT COUNT(*)
            FROM CUSTOMER C1, ORDERS O1
            WHERE C1.CUSTOMER_NUM = O1.CUSTOMER_NUM AND
                O1.ORDER_DATE = O1.ORDER_NUM
     ) <= 1000

我的问题是如何使这种约束发挥作用,例如如何限制每天的订单量。


问题答案:

由于@ruakh已经清除,因此CREATE ASSERTIONPostgreSQL中没有。只需检查SQL命令列表即可。不在那里

您可以使用触发器来结合CHECK约束来更新每个客户的计数,但是您必须涵盖所有相关的DML语句:INSERT,UPDATE,DELETE。可能看起来像这样:

准备现有的客户表:

ALTER 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 <= 1000);

创建触发器函数和触发器:

CREATE OR REPLACE FUNCTION trg_order_upaft()
  RETURNS trigger AS
$BODY$
BEGIN

IF 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$
BEGIN

UPDATE customer
SET    order_ct = order_ct + 1
WHERE  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$
BEGIN

UPDATE customer
SET    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();

我在触发器之后做了所有这些触发器-这就是为什么可以的原因RETURN NULL。在这种情况下,“后”比“前”更可取。如果其他任何条件都可以取消中间的DML语句(如其他触发器),则效果会更好。

如果您一无所获,则最好使用BEFORE触发器。在这种情况下,请确保使触发功能相应地返回NEW / OLD。



 类似资料:
  • PostgreSQL 约束用于规定表中的数据规则。 如果存在违反约束的数据行为,行为会被约束终止。 约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句)。 约束确保了数据库中数据的准确性和可靠性。 约束可以是列级或表级。列级约束仅适用于列,表级约束被应用到整个表。 以下是在 PostgreSQL 中常用的约束。 NOT NULL

  • 错误:关系“test”的新行违反了检查约束“test_status_check”详细信息:失败的行包含(5,2015-07-21,15:00:00,I7,9,NULL,NULL)。

  • 我有一系列复杂的类型级别函数,它们的计算结果如下: 显然,在这种情况下,这个表达式是一个。更一般地说,我们可以说: 有没有办法教GHC推断这一点? 编辑:@chi指出,在某些情况下,GADT可以解决这一问题,但我的特殊情况是: 然后 不能被访问,但是也许GHC应该能够推断出

  • 我想添加一个约束,只在表的一部分中对列强制唯一性。 上面的部分是一厢情愿的想法。 有办法吗?还是应该回到关系绘图板?

  • 我正在使用PostgreSQL 9.5,我想知道是否有可能在ON CONFLICT ON CONSTRAINT语句中包括2个约束的名称 这很好,但我试图做的是在ON CONFLICT ON constraint语句中包含第二个约束。我尝试过下面的选项,但似乎对我不起作用。 如有任何建议,将不胜感激。

  • 问题内容: 给定一个PostgreSQL表,该表具有一个名为的列和一个约束,如下所示: 在这种情况下,我可以提取有关此约束的信息: 但是是否有可能编写一个专门返回未决,成功,失败的查询? 能够在我的应用程序中记住此查询的结果,而不需要维护重复的副本,将是很棒的。 问题答案: 您可以查询系统目录,例如: 使用以下函数 解压缩 字符串: