如果列为空,则触发使用其他表中的值填充列

时间:2018-04-05 14:09:11

标签: sql sqlite triggers

我在这个数据库中使用了sqlite3。

对于作业,我为您的典型食品订购网站建立了一个数据库。此数据库中名为customer_order的表包含客户发出的所有订单。此表还包含订购食物的人的递送地址列。该数据库还包含一个名为customer的表,其中包含每个客户的家庭地址(客户的家庭地址以前缀preffered_为特征)。

由于您可能希望在您不在家时向您的人提供食物,因此在插入customer_order时,与送货地址对应的列可以是除客户家庭地址之外的其他地址

我想要做的是创建一个触发器,当在customer_order表的插入中没有指定传递地址时,该触发器会自动用客户的家庭地址填充传递地址的列。< / p>

到目前为止我的代码是:

CREATE TRIGGER update_delivery_address BEFORE INSERT ON customer_order
WHEN address_street IS NULL
BEGIN
    UPDATE customer_order SET address_street = (SELECT customer.preferred_address_street FROM customer WHERE customer.user_id = customer_order.user_id);
    UPDATE customer_order SET address_number = (SELECT customer.preferred_address_number FROM customer WHERE customer.user_id = customer_order.user_id);
    UPDATE customer_order SET address_zipcode = (SELECT customer.preferred_address_zipcode FROM customer WHERE customer.user_id = customer_order.user_id);
    UPDATE customer_order SET address_city = (SELECT customer.preferred_address_city FROM customer WHERE customer.user_id = customer_order.user_id);
END;

当我声明数据库时,我没有收到任何错误,但是当我尝试插入数据库时​​,我收到以下错误:

Error: near line 108: no such column: address_street

如果有人知道如何解决这个或更好的方法,我们非常感谢任何帮助。

CREATE TABLE `customer_order` (
  `customer_order_id` int(11) NOT NULL PRIMARY KEY,
  `user_id` int(11) DEFAULT NULL,
  `restaurant_id` int(11) NOT NULL,
  `date_created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `preferred_delivery_time` datetime NOT NULL,
  `full_name` varchar(300) NOT NULL,
  `phone_number` varchar(14) NOT NULL,
  `email_address` varchar(300) NOT NULL,
  `address_street` varchar(300) DEFAULT NULL,
  `address_number` varchar(8) DEFAULT NULL,
  `address_zipcode` varchar(6) DEFAULT NULL,
  `address_city` varchar(300) DEFAULT NULL,
  `geolocation` VARCHAR(30) NOT NULL,
  `is_paid` tinyint(4) NOT NULL,
  `notes` text DEFAULT NULL,
  `active` tinyint(4) NOT NULL DEFAULT '1',
  FOREIGN KEY(user_id) REFERENCES user(user_id),
  FOREIGN KEY(restaurant_id) REFERENCES restaurant(restaurant_id)
);

CREATE TABLE `customer` (
  `user_id` int(11) NOT NULL PRIMARY KEY,
  `preferred_address_street` varchar(300) NOT NULL,
  `preferred_address_number` varchar(8) NOT NULL,
  `preferred_address_zipcode` varchar(6) NOT NULL,
  `preferred_address_city` varchar(300) NOT NULL,
  `geolocation` VARCHAR(30) NOT NULL,
  `discount_points_collected` int(11) NOT NULL,
  FOREIGN KEY(user_id) REFERENCES user(user_id)
);

2 个答案:

答案 0 :(得分:1)

我认为你的问题是WHEN子句,它应该使用 new / 表而不是实际表(因为它只是一个INSERT触发器) 是可用的)。

按照: -

  

WHEN子句和触发器操作都可以访问   使用引用插入,删除或更新的行   形成“NEW.column-name”和“OLD.column-name”,其中column-name是   与触发器关联的表中列的名称。   OLD和NEW引用只能用于事件触发器   它们是相关的,如下:

     

INSERT 引用有效

     

更新 OLD 引用   有效

     

DELETE OLD 引用有效

根据CREATE TRIGGER

我也相信你需要一个WHERE子句来限制UPDATE。我还建议一个UPDATE。

因此我建议使用: -

CREATE TRIGGER IF NOT EXISTS update_delivery_address AFTER INSERT ON customer_order
WHEN new.address_street IS NULL
BEGIN
    UPDATE customer_order SET address_street = (SELECT customer.preferred_address_street FROM customer WHERE customer.user_id = customer_order.user_id),
        address_number = (SELECT customer.preferred_address_number FROM customer WHERE customer.user_id = customer_order.user_id),
        address_zipcode = (SELECT customer.preferred_address_zipcode FROM customer WHERE customer.user_id = customer_order.user_id),
        address_city = (SELECT customer.preferred_address_city FROM customer WHERE customer.user_id = customer_order.user_id)
    WHERE customer_order_id = new.customer_order_id;
END;

以上内容已经过测试,但只有一个新订单和有限的客户/用户,还删除了外国餐厅参考,以下用于测试: -

INSERT INTO customer_order VALUES(1,1,10,'2018-10-10','20:30','Fred Bloggs','1234567890','fred@fred.com',null,null,null,null,'????','0','',1);

结果行为: -

enter image description here

替代(更简单)使用行值触发: -

CREATE TRIGGER IF NOT EXISTS update_delivery_address 
    AFTER INSERT ON customer_order
    WHEN new.address_street IS NULL 
    BEGIN
        UPDATE customer_order
        SET (address_street, address_number, address_zipcode, address_city) =
            (SELECT preferred_address_street,
                preferred_address_number,
                preferred_address_zipcode,
                preferred_address_city
            FROM customer
            WHERE customer.user_id = customer_order.user_id
        )
        WHERE customer_order_id = new.customer_order_id;
    END
;

注意我认为这至少需要SQLite发布 3.16.1 (上面是在3.21.0上测试过的。)

  •   

    修复有关在触发器中使用行值的错误(请参阅ticket   8c9458e7)版本3.15.0但直到之后才报告   发布3.16.0版本后的片刻。

用于测试的SQL

DROP TABLE IF EXISTS customer_order;
CREATE TABLE IF NOT EXISTS `customer_order` (
  `customer_order_id` int(11) NOT NULL PRIMARY KEY,
  `user_id` int(11) DEFAULT NULL,
  `restaurant_id` int(11) NOT NULL,
  `date_created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `preferred_delivery_time` datetime NOT NULL,
  `full_name` varchar(300) NOT NULL,
  `phone_number` varchar(14) NOT NULL,
  `email_address` varchar(300) NOT NULL,
  `address_street` varchar(300) DEFAULT NULL,
  `address_number` varchar(8) DEFAULT NULL,
  `address_zipcode` varchar(6) DEFAULT NULL,
  `address_city` varchar(300) DEFAULT NULL,
  `geolocation` VARCHAR(30) NOT NULL,
  `is_paid` tinyint(4) NOT NULL,
  `notes` text DEFAULT NULL,
  `active` tinyint(4) NOT NULL DEFAULT '1',
  FOREIGN KEY(user_id) REFERENCES user(user_id)
  --FOREIGN KEY(restaurant_id) REFERENCES restaurant(restaurant_id)
);
DROP TABLE IF EXISTS customer;
CREATE TABLE `customer` (
  `user_id` int(11) NOT NULL PRIMARY KEY,
  `preferred_address_street` varchar(300) NOT NULL,
  `preferred_address_number` varchar(8) NOT NULL,
  `preferred_address_zipcode` varchar(6) NOT NULL,
  `preferred_address_city` varchar(300) NOT NULL,
  `geolocation` VARCHAR(30) NOT NULL,
  `discount_points_collected` int(11) NOT NULL,
  FOREIGN KEY(user_id) REFERENCES user(user_id)
);
DROP TABLE IF EXISTS user;
CREATE TABLE IF NOT EXISTS user (
    user_id INTEGER PRIMARY KEY,
   user_name TEXT
);
DROP TRIGGER IF EXISTS update_delivery_address;
CREATE TRIGGER IF NOT EXISTS update_delivery_address 
    AFTER INSERT ON customer_order
    WHEN new.address_street IS NULL 
    BEGIN
        UPDATE customer_order
        SET (address_street, address_number, address_zipcode, address_city) =
            (SELECT preferred_address_street,
                 preferred_address_number,
                preferred_address_zipcode,
                        preferred_address_city
                FROM customer
            WHERE customer.user_id = customer_order.user_id
        )
        WHERE customer_order_id = new.customer_order_id;
    END
;
INSERT INTO user (user_name) VALUES ('Fred'),('Bert'),('Harry'),('Tom');
INSERT INTO customer (
                user_id,
                preferred_address_street,
                preferred_address_number,
                preferred_address_zipcode,
                preferred_address_city,
                geolocation,discount_points_collected)
    VALUES (1,'Somerset Blvd','1','12345','Syndey','?????',100);
INSERT INTO customer_order (
                 customer_order_id,
                 user_id,
                 restaurant_id,
                 preferred_delivery_time,
                 full_name,
                 phone_number,
                 email_address,
                 geolocation,
                 is_paid,
                 notes
            )
    VALUES(1,1,20,'21:30','Fred Bloggs','0000 000 000','Fred@Bloggs.com','x',0,'not to note');

答案 1 :(得分:-1)

使用insert join for trigger分别更新每一列。您需要after insert触发器

试试这个

CREATE TRIGGER update_delivery_address ON customer_order
AFTER INSERT
AS
BEGIN
    UPDATE c
    SET address_street = cu.preferred_address_street
    FROM customer_order c
    INNER JOIN INSERTED i ON c.user_id = i.user_id
    INNER JOIN Customer cu ON c.user_id = cu.user_id
    WHERE c.Address_street IS NULL

    UPDATE c
    SET address_number = cu.preferred_address_number
    FROM customer_order c
    INNER JOIN INSERTED i ON c.user_id = i.user_id
    INNER JOIN Customer cu ON c.user_id = cu.user_id
    WHERE c.Address_street IS NULL

    UPDATE c
    SET address_zipcode = cu.preferred_address_zipcode
    FROM customer_order c
    INNER JOIN INSERTED i ON c.user_id = i.user_id
    INNER JOIN Customer cu ON c.user_id = cu.user_id
    WHERE c.Address_street IS NULL

    UPDATE c
    SET address_city = cu.preferred_address_city
    FROM customer_order c
    INNER JOIN INSERTED i ON c.user_id = i.user_id
    INNER JOIN Customer cu ON c.user_id = cu.user_id
    WHERE c.Address_street IS NULL
END;