• 键和约束【2015.12.11】


    约束的定义:

      约束是一种限制,作用于列级或者行级,确保数据符合设计要求和满足数据完整性规则。

    约束的分类:

      1.域约束:作用于列上的约束,比如CHECK和DEFAULT。

      2.实体约束:作用于行上的约束,比如:PRIMARY和UNIQUE。

      3.引用完整性约束:当某列必须与其他列有依赖关系时,FOREIGN KEY。

    约束的种类:

      主键(PRIMARY KEY):行的唯一标识符

      外键(FOREIGN KEY):列依赖于其他列

      UNIQUE约束:列(或者列组合)的值必须唯一

      CHECK约束:设置规则来限制列值

      DEFAULT约束:默认值

    -----------------------------------------------------------------------------------------------------------------------

    创建四个表,用于学习约束

      表1:供货商表(供货商ID,供货商名称)

      创建示范1:(系统默认指定主键名)

    CREATE TABLE dbo.suppliers
    (
        SupplierID        int          NOT NULL
            PRIMARY KEY IDENTITY(1000,1),
        SupplierName    varchar(20)    NOT NULL
    )

      创建示范2:(指定主键名)

    CREATE TABLE dbo.suppliers
    (
        SupplierID        int          NOT NULL
            CONSTRAINT PK_SupplierID PRIMARY KEY IDENTITY(1000,1),
        SupplierName    varchar(20)    NOT NULL
    )

      表2:商品表(商品ID,商品名,供货商ID)

    CREATE TABLE dbo.goods
    (
        GoodsID        int            NOT NULL
            PRIMARY KEY,
        GoodsName   varchar(20)    NOT NULL,
        SupplierID    int            NOT NULL
            FOREIGN KEY REFERENCES suppliers(SupplierID)
    )

      

      表3:库存表(主键ID,商品ID,商品数量)

    CREATE TABLE dbo.purchase
    (
        PurchaseID        int                NOT NULL
            PRIMARY KEY IDENTITY(100,1),
        GoodsID            int                NOT NULL
            FOREIGN KEY REFERENCES goods(GoodsID),
        GoodsTotal        int                NOT NULL,    
        PurchaseDate    smalldatetime    NOT NULL
            DEFAULT(GETDATE())
    )

      表4:商品分类表(分类ID,分类名,父分类ID,分类深度)

    CREATE TABLE dbo.GoodsSort
    (
        SortID        int            NOT NULL
            PRIMARY KEY IDENTITY(1000,1),
        SortName    varchar(20)    NOT NULL,
        ParentID    int            NOT NULL,
        depth        smallint    NOT null
    )

    约束1:主键约束

      主键用以标识一行,必须是唯一值,一个表只能设置一个主键。

      1.创建表时设置主键,如表1的两种创建方式。

      2.在现有表上设置主键: 

         格式: ALTER TABLE 表名 ADD CONSTRAINT 主键名 PRIMARY KEY (列名)

    ALTER TABLE dbo.suppliers
        ADD CONSTRAINT PK_SupplierID
        PRIMARY KEY (SupplierID)

    约束2:外键约束

      在列(依赖列)与列(被依赖列)之间的建立依赖。

      1.某行“依赖列”的值在“被依赖列”上某行都应有匹配的值

      2.修改或者删除“被依赖列”,根据“联级操作”<后面要讲到>的设置,对“依赖列”做相应的处理。

      注意:被依赖列,必须为主键列或者UNIQUE列。

      知识点1:创建表时设置外键约束,如表2创建范例。

      知识点2:在现有表上设置外键:

        格式:ALTER TABLE 依赖表名 ADD CONSTRAINT 外键名 FOREIGN KEY (依赖列名)REFERENCES 被依赖表名(被依赖列名)

    ALTER TABLE dbo.goods
        ADD CONSTRAINT FK_SupplierID
        FOREIGN KEY (SupplierID) REFERENCES suppliers(SupplierID)

       

      知识点3:自引用:依赖列和被依赖列属于同表。

          以表4为例进行“自引用”

          第一步:由于是自引用,必须先有一条记录,然后添加“自引用”外键

            INSERT [dbo].[GoodsSort](SortName,ParentID,depth) VALUES('根类',0,1)

          第二步:设置外键

    ALTER TABLE dbo.GoodsSort
        WITH NOCHECK
        ADD CONSTRAINT FK_ParentID
        FOREIGN KEY (ParentID) REFERENCES GoodsSort(SortID)

          注:这里加了关键词“WITH NOCHECK”,因为之前添加的一条记录不满足先添加的外键规则。使用关键词“WITH NOCHECK”,告诉系统设置外键的时候不检查之前的记录是否符合外键规则。

          第三步:

            如果我们插入:INSERT dbo.GoodsSort(SortName,ParentID,depth) VALUES('C语言',1000,2),插入成功。

            如果我们插入:INSERT dbo.GoodsSort(SortName,ParentID,depth) VALUES('C++语言',1005,2),则插入失败。

            因为1005这个“依赖列”ParentID的值在"被依赖列" SortID 里是不存在的。

      知识点4: 级联操作(我直接理解成依赖操作)

            A.“依赖列”进行操作时候,“被依赖列”会做相应的反应。

            B."被依赖列"进行修改或者删除的时候,"依赖列"会做出相应的反应。

            语法:ON UPDATE {NO ACTION|CASCADE|SET NULL|SET DEFAULT}

                    ON DELETE {NO ACTION|CASCADE|SET NULL|SET DEFAULT}

            默认:NO ACTION,不允许更新或者删除。

            先往对表1里插入三条记录   

            INSERT dbo.suppliers(SupplierName) Values('清华出版社')
            INSERT dbo.suppliers(SupplierName) Values('武汉出版社')
            INSERT dbo.suppliers(SupplierName) Values('希望出版社')

            得到表值,如下:

     SupplierID  SupplierName
     1000  清华出版社
     1001  武汉出版社
     1002  希望出版社

            1.“依赖列”插入记录 

    --语句1:可正常插入
    INSERT dbo.goods(GoodsName,SupplierID) VALUES('C语言基础第一版',1000);
    --语句2:可以正常插入
    INSERT dbo.goods(GoodsName,SupplierID) VALUES('深入C语言',1002);
    --语句3:系统会报错。表suppliers的列SupplierID并含有“1005”这个值
    INSERT dbo.goods(GoodsName,SupplierID) VALUES('C语言算法',1005);

             

             2.删除“被依赖列”记录

             DELETE FROM dbo.suppliers WHERE SupplierID=1000;

             语句报错,因为表suppliers是被依赖表,默认是DELETE行为是NO ACTION

             修改外键的级联操作方式    

    --删除外键 FK_SupplierID
    ALTER TABLE dbo.goods
        DROP CONSTRAINT FK_SupplierID
    
    --重新创建FK_SupplierID,设置UPDATE和DELETE的级联处理方式
    ALTER TABLE dbo.goods
        ADD CONSTRAINT FK_SupplierID
        FOREIGN KEY (SupplierID) REFERENCES suppliers(SupplierID)
        ON UPDATE CASCADE

            再次运行:DELETE FROM dbo.suppliers WHERE SupplierID=1000,删除成功,同时级联删除表[goods]对应的记录。

      

      关于“外键约束”的两个问题:

           1.如果一个表同时设置两个外键,则只能对一个外键设置CASCADE。

           2.如果一个表设置了两个外键,其中有一个设置CASCADE级联操作,则对另外一个外键做DELETE处理的时候同样成功。

           这两个问题有些想不明白。

  • 相关阅读:
    将数据加载到内存中
    反射,Java开发者必须跨越的坎
    Eclipse中Java文件图标由实心J变成空心J的问题
    Maven项目 解决cannot be read or is not a valid ZIP file问题
    MyEclipse中SVN
    常用的 正则验证等
    前台传递数组后台通过json字符串承接和处理
    img标签图片与图片背景的区别和使用场景
    数据库的特性和事务的特性
    redis在EOS7上面进行开启和停止的命令
  • 原文地址:https://www.cnblogs.com/dongdong1979/p/5038040.html
Copyright © 2020-2023  润新知