如何设置必须存在于数据库中

时间:2017-04-11 17:05:41

标签: mysql cascade

我需要帮助。正如你在我的表中看到的,我必须设置主键和forign键,我需要有关此级联更新的帮助。 例如,我有这样的任务: 如果在CATEGORY中更改了Category_Name的值,则此处也应反映更改。

但是这项工作:

如果更改了ORDERED中的OrderID,则此处也应反映更改。 如果删除了ORDERED,则还应删除与该订单关联的任何LINE_ITEM。 如果更改了ITEM的Item_Number,那么此处的更改也应该反映出来。 我不知道如何正确设置这个,我需要帮助才能更好地理解这一点。

CREATE DATABASE TEST1;
USE TEST1;

CREATE TABLE CATEGORY (
CategoryName VARCHAR(35) NOT NULL, 

ShippingPerPound CHAR(4),

OffersAlowed ENUM('y', 'n'), 

CONSTRAINT CATEGORY_PK PRIMARY KEY (CategoryName)

) ENGINE=INNODB;


CREATE TABLE ITEM(
ItemNumber INT UNSIGNED AUTO_INCREMENT, 

Item_Name VARCHAR(35) NOT NULL,

Description VARCHAR(255),

Model VARCHAR(50) NOT NULL,

Price CHAR(8) NOT NULL,

parent_ItemNumber INT,

CategoryName VARCHAR(35),

CONSTRAINT ITEM_PK PRIMARY KEY (ItemNumber),

CONSTRAINT ITEM_CategoryName_fk FOREIGN KEY (CategoryName) REFERENCES 

CATEGORY(CategoryName) ON UPDATE CASCADE) 

ENGINE=INNODB;

CREATE table LINE_ITEM(

Quantitiy INT(255),

Shipping_amounth DECIMAL(4,2),

ItemNumber INT UNSIGNED,

OrderID INT UNSIGNED,

CONSTRAINT LINE_ITEM_PK PRIMARY KEY(ItemNumber),

CONSTRAINT LINE_ITEM_PK PRIMARY KEY(OrderID),

CONSTRAINT LINE_ITEM_OrderID FOREIGN KEY (OrderID) REFERENCES ORDERED(OrderID) ON UPDATE CASCADE),

CONSTRAINT LINE_ITEM_OrderID FOREIGN KEY (OrderID) REFERENCES ORDERED(OrderID) ON UPDATE DELETE),

CONSTRAINT LINE_ITEM_ItemNumber_fk FOREIGN KEY (ItemNumber) REFERENCES ITEM(ItemNumber) ON UPDATE CASCADE)

ENGINE=INNODB;

CREATE TABLE OFFER(

OfferCode varchar(15),

Discount_Amt varchar(35) NOT NULL,

MinAmount DECIMAL(2,2) NOT NULL,

ExpirationDate DATE NOT NULL,

CONSTRAINT OFFER_OfferCode PRIMARY KEY(OfferCode)
)
ENGINE=INNODB;

CREATE TABLE ORDERED(

OrderID INT UNSIGNED AUTO_INCREMENT,

total_cost DECIMAL(8,2),

CONSTRAINT ORDERED_PK PRIMARY KEY (OrderID),

CONSTRAINT OFFER_OfferCode FOREIGN KEY (OrderID) REFERENCES OFFER(OfferCode) ON UPDATE CASCADE),

CONSTRAINT CUSTOMER_CustomerID FOREIGN KEY (CustomerID) REFERENCES CUSTOMER(CustomerID) ON UPDATE CASCADE)
)
ENGINE=INNODB;

1 个答案:

答案 0 :(得分:0)

  

如果在CATEGORY中更改了Category_Name的值,则更改应反映在[引用类别的表格]中。

你有XY Problem。您已经选择了解决问题的方法(使用级联更新)并询问了相关问题。它不是一个好的解决方案,它只是真实的论文。相反,你应该问一下真正的问题。

真正的问题是你有重复数据,CategoryName存储在两个地方。问题是如何解决这个问题?答案是重新设计模式以消除重复。

查看Category表会显示 real real 问题,CategoryName是主键,因此它将在其他表中引用。但是,如果CategoryName可以改变它,那么主键的选择就会很糟糕。相反,使用一个简单的自动递增整数作为主键,问题就消失了。

create table Category (
    ID integer auto_increment primary key,
    Name varchar(255) not null, 
    ShippingPerPound CHAR(4),
    OffersAlowed ENUM('y', 'n'), 
);

现在可以使用CategoryID integer references category(id)引用类别。类别名称可以根据需要进行更改。任何需要知道类别名称的查询都必须join Category on Category.id = CategoryID;像这样简单的连接很便宜。

  

如果更改了ITEM的Item_Number,则更改应反映在[引用项目的表格]中。

同样的问题:如果主键可以改变,那么它不是一个好的主键。由于Item_Number是自动递增的,所以它永远不会改变,所以你可能会担心一个不存在的问题。

如果Item_Number可以更改,那么您需要两列。一个用于不可变主键,只需将其称为id,另一个用于可变Item_Number。对于大多数列而言,它们可以是相同的,这很好,它只是为每列添加4个字节。

请注意,我将名称约束增加到255.将业务规则(如名称大小限制)放入数据库架构中是一种不好的做法。数据库不应该限制设计选择,并且没有技术理由限制它:varchar(255)中的30个字符占用varchar(30)中30个字符的空间。

我也质疑为什么ShippingPerPoundchar(4)。它似乎应该是一个数字,可能是numeric(9,2)钱。 numeric将存储确切的值并且不会出现浮点错误,它是一个不错的选择。

最后,我要小心不要使用unsigned integer作为主键。是的,它会使你的密钥空间增加一倍,但我可以保证引用该密钥的人会忘记并使用普通的有符号整数。如果你达到20亿行,那么你可能会如此迅速地增长,以至于你比第一次快得多地吹过接下来的20亿,所以它是不值得的。如果您真的关心密钥空间,请使用bigint或UUID。但这不是你现在需要担心的事情,如果表格成为问题,可以在以后更改表格。但它不太可能是物品的问题,因为你不太可能拥有20亿件物品。 Keyspace耗尽是指在记录事物或跟踪销售的表格中发生的事情,随着您获得更多用户而呈指数增长的事物;没有手动输入仓库数据。

旧的数据库指南有时会鼓励尝试将数据用作主键或对存储大小设置不必要的限制等不良做法。当磁盘和CPU非常有限,或者当列大小固定时,可能有意义,但现在没有意义。自动递增的整数主键是一个很好的默认选择。