SQL sever中的约束

目录

一、约束定义

二、约束分类

三、定义约束

四、约束相关语法格式

4.1主键约束(Primary Key Constraint):

4.2外键约束(Foreign Key Constraint):

4.3唯一约束(Unique Constraint):

4.4检查约束(Check Constraint):

4.5默认约束(Default Constraint):

4.6非空约束(Not Null Constraint):

五、约束用法

5.1主键约束(Primary Key Constraint):

5.1.1验证主键约束:

5.1.2注意事项:

5.2外键约束(Foreign Key Constraint):

5.2.1验证外键约束:

5.2.2注意事项:

5.3唯一约束(Unique Constraint):

5.3.1验证唯一约束:

5.3.2注意事项:

5.4检查约束(Check Constraint):

5.4.1验证检查约束:

5.4.2注意事项:

5.5默认约束(Default Constraint):

5.5.1验证默认约束:

5.5.2注意事项:

5.6非空约束(Not Null Constraint):

5.6.1验证非空约束:

​编辑5.6.2注意事项:

 六、约束参考学习


一、约束定义

约束是用于定义和实施表的规则和限制,以确保数据的完整性和一致性。

即对一张表中的属性操作进行限制。

二、约束分类

通过定义约束,可以对数据库中的数据进行限制,以下是常见的约束:

  • 1. 主键约束(Primary Key Constraint):

   - 用途:用于唯一标识表中的每一行数据,并且不允许为空。
   - 语法:`PRIMARY KEY (column1, column2, ...)`。

  • 2. 外键约束(Foreign Key Constraint):

   - 用途:用于建立表与表之间的关系,确保引用其他表中存在的值。
   - 语法:`FOREIGN KEY (column1, column2, ...) REFERENCES parent_table (parent_column1, parent_column2, ...)`。

  • 3. 唯一约束(Unique Constraint):

   - 用途:确保表中的某个列或一组列的值是唯一的。
   - 语法:`UNIQUE (column1, column2, ...)`。

  • 4. 检查约束(Check Constraint):

   - 用途:定义一个布尔表达式来评估插入或更新的值是否满足特定条件。
   - 语法:`CHECK (condition)`。

  • 5. 默认约束(Default Constraint):

   - 用途:为给定列提供默认值,如果插入或更新操作未指定该列的值,则将使用默认值。
   - 语法:`DEFAULT value`。

  • 6. 非空约束(Not Null Constraint):

   - 用途:确保列不允许包含空值。
   - 语法:`column_name datatype NOT NULL`。

约束可以在创建表时直接定义,也可以在后期通过修改表结构来添加或删除。使用约束可以提高数据库的完整性和一致性,防止无效或不符合规范的数据被插入到表中。

三、定义约束

通过表的创建语句或者修改表结构的语句来定义约束。以下是两种常见的方法:

  • 3.1. 在创建表时定义约束:

   - 使用CREATE TABLE语句来创建表,并在列定义之后添加约束。
   - 例如,创建一个包含主键和唯一约束的表:

CREATE TABLE TableName (
         column1 datatype CONSTRAINT PK_ConstraintName PRIMARY KEY,
         column2 datatype CONSTRAINT UK_ConstraintName UNIQUE,
         ...
     );
  • 3.2. 使用ALTER TABLE语句修改表结构来添加约束:

   - 使用ALTER TABLE语句来为已存在的表添加、修改或删除约束。
   - 例如,为现有表添加外键约束:

 ALTER TABLE TableName
     ADD CONSTRAINT FK_ConstraintName FOREIGN KEY (column1) REFERENCES ParentTable (parent_column);

注意:

      无论是在表创建过程中还是在后期修改表结构时定义约束,都需要指定约束的类型(如主键、外键等)以及相关的信息(如列名、引用表等)。此外,还可以为约束指定名称以便更好地标识和管理。约束的定义通常遵循特定的语法规则,但具体的语法格式可能会因数据库版本和具体需求而略有不同。

       约束的定义可能受到其他因素的限制,如数据类型的兼容性、表的引擎类型等。在定义约束之前,建议对表结构和约束条件进行仔细设计和规划,确保其适用于数据模型和业务需求。

四、约束相关语法格式

使用以下语法格式来创建、删除和修改六种常见的约束类型:主键约束、唯一约束、外键约束、检查约束、默认约束和非空约束。

4.1主键约束(Primary Key Constraint):

--1.创建主键约束
-- 语法格式:
ALTER TABLE 表名
ADD CONSTRAINT 约束名 PRIMARY KEY (列名);

-- 示例:
ALTER TABLE Employees
ADD CONSTRAINT PK_Employees PRIMARY KEY (EmployeeID);

--2.删除主键约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;

-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT PK_Employees;

--3.修改主键约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;

ALTER TABLE 表名
ADD CONSTRAINT 新约束名 PRIMARY KEY (列名);

-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT PK_Employees;

ALTER TABLE Employees
ADD CONSTRAINT PK_Employees_New PRIMARY KEY (EmployeeID);

4.2外键约束(Foreign Key Constraint):

--1.创建外键约束
-- 语法格式:
ALTER TABLE 子表名
ADD CONSTRAINT 约束名 
FOREIGN KEY (子表关联列)
REFERENCES 主表名 (主表关联列);

-- 示例:
ALTER TABLE Employees
ADD CONSTRAINT FK_Employees_Departments
FOREIGN KEY (DepartmentID)
REFERENCES Departments(DepartmentID);


--2.删除外键约束
-- 语法格式:
ALTER TABLE 子表名
DROP CONSTRAINT 约束名;

-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT FK_Employees_Departments;



--3.修改外键约束
-- 语法格式:
ALTER TABLE 子表名
DROP CONSTRAINT 约束名;

ALTER TABLE 子表名
ADD CONSTRAINT 新约束名 FOREIGN KEY (子表关联列)
REFERENCES 主表名 (主表关联列);

-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT FK_Employees_Departments;

ALTER TABLE Employees
ADD CONSTRAINT FK_Employees_Departments_New
FOREIGN KEY (DepartmentID)
REFERENCES Departments(DepartmentID);


4.3唯一约束(Unique Constraint):

--1.创建唯一约束
-- 语法格式:
ALTER TABLE 表名
ADD CONSTRAINT 约束名 UNIQUE (列名);

-- 示例:
ALTER TABLE Employees
ADD CONSTRAINT UQ_Employees_Email UNIQUE (Email);


--2.删除唯一约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;

-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT UQ_Employees_Email;


--3.修改唯一约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;

ALTER TABLE 表名
ADD CONSTRAINT 新约束名 UNIQUE (列名);

-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT UQ_Employees_Email;

ALTER TABLE Employees
ADD CONSTRAINT UQ_Employees_Email_New UNIQUE (Email);


4.4检查约束(Check Constraint):

--1.创建检查约束
-- 语法格式:
ALTER TABLE 表名
ADD CONSTRAINT 约束名 CHECK (条件);

-- 示例:
ALTER TABLE Employees
ADD CONSTRAINT CK_Employees_Salary CHECK (Salary > 0);



--2.删除检查约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;

-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT CK_Employees_Salary;




--3.修改检查约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;

ALTER TABLE 表名
ADD CONSTRAINT 新约束名 CHECK (条件);

-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT CK_Employees_Salary;

ALTER TABLE Employees
ADD CONSTRAINT CK_Employees_Salary_New CHECK (Salary > 1000);


4.5默认约束(Default Constraint):

--1.创建默认约束
-- 语法格式:
ALTER TABLE 表名
ADD CONSTRAINT 约束名 DEFAULT 默认值 FOR 列名;

-- 示例:
ALTER TABLE Employees
ADD CONSTRAINT DF_Employees_HireDate DEFAULT GETDATE() FOR HireDate;




--2.删除默认约束
-- 语法格式:
ALTER TABLE 表名
ALTER COLUMN 列名 DROP DEFAULT;

-- 示例:
ALTER TABLE Employees
ALTER COLUMN HireDate DROP DEFAULT;




--3.修改默认约束
-- 语法格式:
ALTER TABLE 表名
DROP CONSTRAINT 约束名;

ALTER TABLE 表名
ADD CONSTRAINT 新约束名 DEFAULT 默认值 FOR 列名;

-- 示例:
ALTER TABLE Employees
DROP CONSTRAINT DF_Employees_HireDate;

ALTER TABLE Employees
ADD CONSTRAINT DF_Employees_HireDate_New DEFAULT GETDATE() FOR HireDate;


4.6非空约束(Not Null Constraint):

--1.创建非空约束
-- 语法格式:
ALTER TABLE 表名
ALTER COLUMN 列名 数据类型 NOT NULL;

-- 示例:
ALTER TABLE Employees
ALTER COLUMN Address VARCHAR(100) NOT NULL;




--2.删除非空约束
-- 语法格式:
ALTER TABLE 表名
ALTER COLUMN 列名 数据类型 NULL;

-- 示例:
ALTER TABLE Employees
ALTER COLUMN Address VARCHAR(100) NULL;





--3.修改非空约束
-- 语法格式:
ALTER TABLE 表名
ALTER COLUMN 列名 数据类型 NOT NULL;

-- 示例:
ALTER TABLE Employees
ALTER COLUMN Address VARCHAR(200) NOT NULL;


注意:

通过使用以上的语法格式,可以对指定表的约束进行创建、修改和删除。

  1. 在修改约束之前,要确保了解并满足新的约束要求,并确保没有数据违反约束。
  2. 在删除约束之前,要确保没有数据依赖于该约束,并且备份数据以防止意外的数据损失。 
  3. 对于某些约束,需要先删除约束才能修改列的定义,然后再重新添加约束。在实际操作中,一定要谨慎处理对表结构的改变,并确保在进行任何更改之前备份数据。

五、约束用法

创建表Employees1,来完成各种约束的创建,用法如下:

5.1主键约束(Primary Key Constraint):

通过CONSTRAINT PK_Employees PRIMARY KEY指定EmployeeID作为主键,保证每行数据的唯一性。

-- 创建表 并定义主键
CREATE TABLE Employees1 (
    EmployeeID INT CONSTRAINT PK_Employees PRIMARY KEY,
    FirstName VARCHAR(50) NOT NULL,
    LastName VARCHAR(50) NOT NULL,
    DepartmentID INT,
    Salary DECIMAL(10, 2) DEFAULT 0
);

向表中插入数据;

-- 插入数据
INSERT INTO Employees1 
         (EmployeeID, FirstName, LastName, DepartmentID,  Salary)
VALUES
    (1, 'John', 'Doe', 1,  5000),
    (2, 'Jane', 'Smith', 2,  6000),
    (3, 'David', 'Johnson', 1,  4500);

 查询如下:

5.1.1验证主键约束:

向表中试图插入具有相同EmployeeID的记录,比如:

-- 插入数据(主键验证)
INSERT INTO Employees1 
         (EmployeeID, FirstName, LastName, DepartmentID,  Salary)
VALUES
    (1, 'tom', 'Min', 2,  5500)

执行结果如下:

5.1.2注意事项:

在使用主键约束时,需要注意以下几点:

  • 1. 唯一性:主键值必须在表中是唯一的。确保每行的主键值都不相同,以避免违反主键约束。如果插入或更新操作导致重复的主键值,将会触发主键冲突错误。
  • 2. 非空性:主键列不能为空(即不允许NULL值)。因此,在定义主键约束之前,应该确保列上没有NULL值。如果尝试将NULL值插入主键列,将会触发非空约束错误。
  • 3. 不可修改性:主键值一旦设置,通常是不允许更改的。这是为了确保主键的稳定性和数据完整性。如果确实需要更改主键值,那么首先需要删除原有的行,然后插入新的行。
  • 4. 主键命名:给主键约束命名时,应该选择有意义和描述性的名称,以提高代码的可读性和可维护性。通常使用"PK_"作为主键约束名称的前缀,以便于识别。
  • 5. 引用关系:主键通常被用来建立表与其他表的关联(外键引用)。当表存在外键引用时,删除或修改主键值可能会影响到其他表的数据完整性。在进行任何更改之前,请谨慎评估和处理相关的外键关系。
  • 6. 聚集索引:主键约束默认会创建一个聚集索引。聚集索引决定了表中数据的物理存储顺序。要根据查询需求和性能优化考虑是否使用聚集索引,并选择合适的列作为聚集索引的键。
  • 7. 复合主键:可以通过使用多个列来定义复合主键。在使用复合主键时,确保每个组合值都是唯一的,并且所有组合值都不为空。
  • 8. 自增长主键:可以使用IDENTITY属性或SEQUENCE对象来生成自增长的主键值。自增长主键为每个新行分配一个唯一的、递增的值。要正确使用自增长主键,请确保未手动插入主键值。

总结:

使用主键约束可以确保表中的每行都具有唯一标识并且非空。在使用主键约束时,要注意唯一性、非空性、不可修改性、命名规范以及与其他表的引用关系。这样可以确保数据的完整性和一致性,并提高数据库的性能和可维护性。 

5.2外键约束(Foreign Key Constraint):

创建表Departments1,并向表内插入数据:

-- 创建Departments1表
CREATE TABLE Departments1 (
    DepartmentID INT CONSTRAINT PK_Departments PRIMARY KEY,
    DepartmentName VARCHAR(50) NOT NULL
);

-- 向Departments表插入数据
INSERT INTO Departments1 (DepartmentID, DepartmentName)
VALUES
    (1, 'Sales'),
    (2, 'Marketing');

查询如下:

 

然后使用ALTER TABLE语句添加一个名为FK_Employees_Departments的外键约束,将DepartmentID列与Departments1表的DepartmentID列关联起来,确保引用的值存在于父表中。

-- 添加外键约束
ALTER TABLE Employees1
ADD CONSTRAINT FK_Employees_Departments
FOREIGN KEY (DepartmentID)
REFERENCES Departments1(DepartmentID);

5.2.1验证外键约束:

①向表中试图插入具有不存在的DepartmentID的记录,比如:

-- 插入数据(外键验证)
INSERT INTO Employees1 
         (EmployeeID, FirstName, LastName, DepartmentID,  Salary)
VALUES
    (4, 'tom', 'Min', 3,  5500)

执行结果如下: 

②更新Departments1表中被引用的部门记录 ,比如:

--更新Departments1表中被引用的部门记录 (外键验证)
update Departments1 set  DepartmentID=3;

 执行结果如下:

③删除Departments1表中被引用的部门记录,比如:

--删除Departments1表中被引用的部门记录 (外键验证)
delete from Departments1 where  DepartmentID=1;

 执行结果如下:

5.2.2注意事项:

在使用外键约束时,需要注意以下几点:

  • 1. 引用完整性:外键约束用于维护表之间的引用完整性。在定义外键约束之前,应确保所引用的主键或唯一键列存在,并且已经创建了相应的主键或唯一约束。
  • 2. 数据一致性:外键约束确保关联表中的数据保持一致。插入或更新包含外键的行时,确保引用值存在于关联表中,以避免违反外键约束。
  • 3. 级联操作:可以定义级联操作来处理与外键关联的操作。级联操作指定了当引用表中的数据发生改变时,对关联表中的数据的处理方式。常见的级联操作包括级联删除和级联更新。
  • 4. 删除限制:默认情况下,外键约束会阻止删除关联表中被引用的行。如果要删除关联表中的数据,必须首先删除引用它的所有行,或者定义级联删除操作来自动删除相关行。
  • 5. 修改限制:默认情况下,外键约束会阻止修改关联表中被引用的主键或唯一键列。如果需要修改关联列的值,必须先删除外键约束,然后进行修改。修改完成后,可以重新创建外键约束。
  • 6. 外键命名:给外键约束命名时,应选择有意义和描述性的名称,以提高代码的可读性和可维护性。通常使用"FK_"作为外键约束名称的前缀,以便于识别。
  • 7. 联接效率:外键约束可能会影响查询的性能。因此,在设计和使用外键时,要注意查询的联接操作,并根据具体需求考虑是否需要创建索引来优化查询性能。
  • 8. 外键顺序:在创建多个外键约束时,外键约束的顺序可能会对操作产生影响。如果存在循环引用,即多个表相互引用,必须谨慎处理外键的顺序和依赖关系。

总结:

在使用外键约束时,要确保引用关系的完整性,并注意数据的一致性、级联操作、删除和修改的限制。合理命名外键约束,考虑查询效率和索引的使用,以确保数据库的正常运行和性能优化。 

5.3唯一约束(Unique Constraint):

向Employees1插入列Email,

ALTER TABLE Employees1
ADD Email VARCHAR(50);

查询如下:

         

通过ALTER TABLE语句添加一个名为UQ_Employees_Email的唯一约束,确保Email列的值在表中是唯一的。

-- 添加唯一约束
ALTER TABLE Employees1
ADD CONSTRAINT UQ_Employees_Email
UNIQUE (Email);

执行结果如下:

根据给出的错误消息,以下是该问题的概要:

  • - 错误消息 1505 表示在创建唯一索引时发现重复的键值。
  • - 错误消息指出重复的键值为 `<NULL>`,这意味着在 `dbo.Employees1` 表中有多个空值。
  • - 错误消息 1750 指示由于先前的错误消息导致无法创建约束。

这些错误消息表明在尝试创建名为 `UQ_Employees_Email` 的唯一索引时遇到问题。索引名称和表对象名称之间存在冲突,而且在索引列中存在重复的空键值。

为了解决这个问题,可以采取以下步骤:

  • 1. 首先,检查数据库中的 `dbo.Employees1` 表以确认是否存在重复的空键值。可以运行一个查询来找到重复的空值并处理它们。
SELECT *
FROM dbo.Employees1
WHERE Email IS NULL
  • 2. 处理重复的空值后,再次尝试创建唯一索引。确保将索引名称与表对象名称区分开,并确保索引列中不再包含重复的键值。
  • 3. 如果问题仍然存在,检查其他约束或触发器是否可能导致冲突。可以检查表定义、其他索引定义、约束和触发器等来排除其他潜在的冲突源。

如果以上步骤都没有解决问题,可能需要进一步检查数据库架构和数据模型以确定导致此问题的根本原因。

对表中Email列数据更新:

--更新Employees1表数据
update Employees1 set  Email='john.doe@example.com' where EmployeeID=1;
update Employees1 set  Email='jane.smith@example.com' where EmployeeID=2;
update Employees1 set  Email='david.johnson@example.com' where EmployeeID=3;

 查询结果如下:

此时再次执行添加唯一键约束,执行结果如下:

 

5.3.1验证唯一约束:

唯一约束用于确保表中的某一列或一组列的值是唯一的。要验证唯一约束是否按预期工作,可以尝试插入或更新数据,检查是否违反了唯一约束条件。有以下几种验证唯一约束的方法:

1. 尝试插入重复的值:

  •    - 在执行INSERT语句时,如果尝试插入具有与已存在记录相同的唯一值的数据,将触发唯一约束错误。
  •    - 例如,在`Employees1`表中,如果尝试插入具有相同Email的记录,将违反唯一约束。
-- 插入数据
INSERT INTO Employees1 (EmployeeID, FirstName, LastName, DepartmentID, Salary, Email)
VALUES
    (4, 'tom', 'Min', 3,  5500,'john.doe@example.com' )

执行结果如下: 

2. 尝试更新为重复的值:

  •    - 使用UPDATE语句时,如果将某一列更新为已存在于表中其他记录中的唯一值,将触发唯一约束错误。
  •    - 例如,在`Employees1`表中,如果将一个员工的Email更新为已经存在的Email,将违反唯一约束。
--更新数据
update Employees1 set  Email='john.doe@example.com' where EmployeeID=2;

执行结果如下: 

3. 查询已存在的唯一值:

  •    - 使用SELECT语句查询某一列的值,然后检查是否存在重复的唯一值。
  •    - 例如,在`Employees1`表中,可以使用以下查询来查找是否有重复的Email:
    SELECT Email, COUNT(*) AS Count
     FROM Employees1
     GROUP BY Email
     HAVING COUNT(*) > 1;

执行结果如下: 

 

通过执行上述这些操作并观察结果,如果出现唯一约束错误或查询返回重复的唯一值,就表示唯一约束成功地阻止了重复数据的插入或更新。

注意:

当唯一约束被定义并且数据违反约束时,SQL Server会抛出唯一约束冲突的错误信息,提供相关的细节和错误代码,帮助识别和解决问题。

5.3.2注意事项:

唯一约束(Unique Constraint)用于确保列或列组合的值是唯一的,需要注意以下几点:

  • 1. 唯一性:唯一约束要求列或列组合中的值在表中是唯一的,不允许重复。确保每行的唯一约束值都不相同,以避免违反唯一性约束。
  • 2. NULL值:唯一约束默认可以包含一个NULL值。这意味着多个NULL值可以存在于列或列组合中而不违反唯一性约束。如果想要禁止NULL值重复,可以创建一个索引来实现。
  • 3. 索引创建:唯一约束会自动创建一个唯一索引来支持唯一性验证。确保在设计和使用唯一约束时,对相关列或列组合创建适当的索引,以提高查询效率。
  • 4. 复合唯一约束:可以使用多个列来定义复合唯一约束。复合唯一约束意味着多个列的组合必须是唯一的。在创建复合唯一约束时,确保每个组合值都是唯一的,且所有组合值都不为空。
  • 5. 唯一约束命名:给唯一约束命名时,应选择有意义和描述性的名称,以提高代码的可读性和可维护性。通常使用"UQ_"作为唯一约束名称的前缀,以便于识别。
  • 6. 修改限制:修改唯一约束会影响现有数据的一致性。如果要更改唯一约束的列或列组合,必须先删除原有的唯一约束,然后重新创建新的唯一约束。
  • 7. 外键引用:唯一约束常用于引用表之间的关系。如果将唯一约束用作外键的引用,需要确保被引用的唯一值与外键列或列组合相匹配,并且满足引用完整性的要求。
  • 8. 性能影响:唯一约束的索引可能会对插入、更新和删除操作的性能产生影响。在设计和使用唯一约束时,要平衡数据完整性和性能需求,根据具体情况选择是否使用唯一约束。

总结:

在使用唯一约束时,要确保唯一性、索引的创建和命名、复合唯一约束的定义和数据完整性的保持。同时,需要注意与外键引用、修改约束和性能方面的考虑,以确保数据库的正常运行和性能优化。 

5.4检查约束(Check Constraint):

使用ALTER TABLE语句添加一个名为CHK_Employees_Salary的检查约束,限制Salary列的值必须在0和100000之间。

-- 添加检查约束
ALTER TABLE Employees1
ADD CONSTRAINT CHK_Employees_Salary
CHECK (Salary >= 0 AND Salary <= 100000);

5.4.1验证检查约束:

检查约束用于定义一个布尔表达式来评估插入或更新的值是否满足特定条件。要验证检查约束是否按预期工作,可以尝试执行插入或更新操作,并观察是否违反了定义的检查约束条件。有以下几种验证检查约束的方法:

1. 尝试插入或更新不满足条件的值:

  •    - 在执行INSERT或UPDATE语句时,如果插入或更新的值不符合检查约束的条件,将触发检查约束错误。
  •    - 例如,在`Employees1`表中,假设我们有一个检查约束限制Salary列的取值范围必须在0到100000之间,如果尝试插入或更新一个超出此范围的Salary值,将违反检查约束。
--插入数据(验证检查约束)
INSERT INTO Employees1 
         (EmployeeID, FirstName, LastName, DepartmentID,  Salary,Email)
VALUES
    (4, 'tom', 'Min', 3, 100001,'Tom.doe@example.com')

执行结果如下: 

2. 查询违规的值:

  •    - 使用SELECT语句查询相关列的数据,然后评估是否存在违反检查约束条件的值。
  •    - 例如,在`Employees1`表中,可以使用以下查询来查找Salary不在指定范围内的记录:
SELECT *
FROM Employees1
WHERE Salary < 0 OR Salary > 100000;

 执行结果如下:

通过执行上述这些操作并观察结果,如果出现检查约束错误或查询返回违反检查约束条件的行,就表示检查约束成功地阻止了不符合条件的数据的插入或更新。

请注意,当检查约束被定义并且数据违反约束时,SQL Server会抛出检查约束失败的错误信息,提供相关细节和错误代码,以帮助识别和解决问题。

5.4.2注意事项:

需要注意以下几点:

  • 1. 检查条件:检查约束用于限制列的取值范围。在定义检查约束时,要确保检查条件是准确的、完整的,并且符合业务规则和需求。
  • 2. 约束命名:给检查约束命名时,应选择有意义和描述性的名称,以提高代码的可读性和可维护性。通常使用"CK_"作为检查约束名称的前缀,以便于识别。
  • 3. 多列检查约束:可以使用多个列来定义复杂的检查约束。在使用多列检查约束时,要确保检查条件涵盖了所有相关列,并且能够正确地验证数据的完整性。
  • 4. 修改限制:修改检查约束可能会影响现有数据的一致性。如果要更改检查约束的条件,必须先删除原有的检查约束,然后重新创建新的检查约束。
  • 5. 性能影响:应谨慎使用复杂或耗时的检查条件,因为它们可能会对插入、更新和查询操作的性能产生影响。在设计和使用检查约束时,要平衡数据完整性和性能需求。
  • 6. 默认值冲突:如果存在默认值并且检查约束条件与默认值冲突,将无法插入或更新数据。确保检查约束的条件和默认值是兼容的,并且不会导致冲突。
  • 7. 特殊字符转义:如果检查约束条件包含特殊字符,如引号、百分号等,要进行适当的转义处理,以避免语法错误或意外行为。
  • 8. 跨表检查约束:检查约束可以跨多个表进行定义。在跨表检查约束时,要确保引用的表和列是正确的,并且能够满足数据完整性和业务规则的要求。

总结:

在使用检查约束时,要确保检查条件的准确性和完整性,合理命名约束,注意修改约束的影响和检查条件与默认值的兼容性。同时,要注意性能方面的考虑,并在需要的情况下进行特殊字符转义和跨表检查约束的定义。这样可以确保数据库中的数据满足业务规则和完整性要求。 

5.5默认约束(Default Constraint):

向Employees1表插入新列HireDate并更新数据:

--添加新列HireDate
ALTER TABLE Employees1
ADD HireDate date;

update Employees1 set  HireDate='2021-1-1' where EmployeeID=1;
update Employees1 set  HireDate='2021-2-1' where EmployeeID=2;
update Employees1 set  HireDate='2021-3-1' where EmployeeID=3;

通过ALTER TABLE语句修改HireDate列的定义,设置一个名为DF_Employees_HireDate的默认约束,使得在插入新记录时,如果未提供HireDate的值,则默认为当前日期(GETDATE())。

-- 添加默认约束
-- 修改 HireDate 列的数据类型和允许 NULL 值
ALTER TABLE Employees1
ALTER COLUMN HireDate DATE NULL;

-- 添加 HireDate 列的默认约束
ALTER TABLE Employees1
ADD CONSTRAINT DF_Employees_HireDate DEFAULT GETDATE() FOR HireDate;

5.5.1验证默认约束:

向Employees1表插入新数据:

--插入数据(验证默认约束)
INSERT INTO Employees1 
         (EmployeeID, FirstName, LastName, DepartmentID,  Salary,Email)
VALUES
    (4, 'tom', 'Min', 2, 8000,'Tom.doe@example.com')

执行结果如下: 

5.5.2注意事项:

使用默认约束时,需要注意以下几点:      

  • 1. 默认值选择:默认约束用于指定列在没有明确提供值时的默认值。在选择默认值时,要确保它符合业务规则,并且与列的数据类型兼容。
  • 2. NULL值处理:默认约束可以包含一个NULL值作为默认值。如果想要禁止列使用NULL值作为默认值,可以在创建表时或后续使用ALTER TABLE语句添加NOT NULL约束。
  • 3. 默认约束命名:给默认约束命名时,应选择有意义和描述性的名称,以提高代码的可读性和可维护性。通常使用"DF_"作为默认约束名称的前缀,以便于识别。
  • 4. 修改限制:修改默认约束可能会影响现有数据的一致性。如果要更改默认值,必须先删除原有的默认约束,然后重新创建新的默认约束。
  • 5. 多列默认约束:可以为多个列定义相同的默认约束。在使用多列默认约束时,要确保默认值在所有相关列上都是适用的,并且与数据类型兼容。
  • 6. 跨表默认约束:默认约束可以跨多个表进行定义。在跨表默认约束时,要确保引用的表和列是正确的,并且能够满足数据完整性和业务规则的要求。
  • 7. 性能影响:如果默认值涉及复杂计算或查询操作,可能会对插入和更新操作的性能产生影响。要谨慎选择默认值,避免过度复杂或耗时的操作。
  • 8. 默认约束的顺序:如果存在多个默认约束,并且有依赖关系,确保按正确的顺序创建这些约束,以避免依赖错误。

总结:

在使用默认约束时,要选择合适的默认值,注意NULL值的处理、命名约束、修改约束的影响和多列/跨表默认约束的定义。同时,要注意默认值的性能影响和约束的顺序,以确保数据库中的数据具有适当的默认值并满足业务规则。 

5.6非空约束(Not Null Constraint):

向Employees1表插入新列Address并更新数据:

--添加新列Address
ALTER TABLE Employees1
ADD Address NVARCHAR(100);

update Employees1 set  Address='M' where EmployeeID=1;
update Employees1 set  Address='N' where EmployeeID=2;
update Employees1 set  Address='W' where EmployeeID=3;
update Employees1 set  Address='V' where EmployeeID=4;

使用ALTER TABLE语句修改Address列的定义,确保该列不允许为空值。

-- 添加非空约束
ALTER TABLE Employees1
ALTER COLUMN Address NVARCHAR(100) NOT NULL;

5.6.1验证非空约束:

--插入数据(验证非空约束)
INSERT INTO Employees1 
         (EmployeeID, FirstName, LastName, DepartmentID,  Salary,Email)
VALUES
    (5, 'key', 'Maxx', 2, 7000,'key.doe@example.com')

执行结果如下: 

 插入正确数据进行观察:

--插入数据(验证非空约束)
INSERT INTO Employees1 
         (EmployeeID, FirstName, LastName, DepartmentID,  Salary,Email,Address)
VALUES
    (5, 'key', 'Maxx', 2, 7000,'key.doe@example.com','m')

执行结果如下: 

5.6.2注意事项:

使用非空约束时,需要注意以下几点:

  • 1. 列定义:非空约束用于限制列不允许为空值。在定义表结构时,需要明确指定哪些列需要应用非空约束。
  • 2. 默认值:如果未提供值且列具有默认值,则非空约束不会阻止插入操作。确保在设计表时,明确为不允许为空的列提供适当的默认值或规定其必须显式提供值。
  • 3. 修改限制:如果要将已具有数据的列更改为非空约束,必须先确定所有现有行都包含有效的值,然后才能添加非空约束。
  • 4. 空字符串:非空约束只针对空值(NULL),而不会限制空字符串。如果希望禁止空字符串,则需要使用非空约束和额外的检查约束来实现。
  • 5. 外键关系:在定义外键关系时,注意引用列是否允许为空。如果主表中的被引用列是非空约束,那么外键列也应该是非空约束,以确保引用完整性。
  • 6. 默认约束冲突:如果某个列既有非空约束又有默认约束,并且二者存在冲突,例如默认值为NULL,则会导致冲突。确保默认约束与非空约束兼容,以避免此类冲突。
  • 7. 数据完整性:非空约束可确保数据完整性,但需要注意在应用非空约束之前,已经存在的数据可能包含空值。在应用非空约束之后,需要确保现有数据符合约束条件。
  • 8. 修改数据:非空约束限制了对该列的更新和插入操作中的空值。确保在进行这些操作时,提供了非空的值,否则将违反非空约束。

总结:

在使用非空约束时,要注意对列的定义、默认值的处理,修改限制和数据完整性的考虑。同时,需要注意与外键关系和默认约束的兼容性,以确保数据库中的数据满足非空约束并保持一致性。

 六、约束参考学习

在Oracle学习过程中,我也总结梳理了一篇关于约束的相关笔记,篇名是【Oracle中的约束】,笔记链接如下:http://t.csdn.cn/e1hx6

其实SQL sever、Oracle、MySQL等数据库他们的约束没有特别大的区别,有异曲同工之妙,我们均可以参考学习,然后自己做个梳理汇总,渐渐的就能理解并熟练运用。

最后感谢大家的支持,文章如有错误还请指正!

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SQL sever 2008 Rar! ?s X<t ? ? ? ?祕BwL0 17240671-1.sql ?<9--2018年3月9日 --1.查询course表的所有信息(所有行所有列) USE Xk GO SELECT * FROM Course --有哪些种类的选修课?学分是多少 USE XK GO SELECT Kind,Credit FROM Crouse GO 修改列名字 SELECT '课程种类'=Kind,'学分'=Credit FROM Course GO --查询Course表的前10行 SELECT TOP 10 * FROM Course GO --查询Course表的前10%行 USE Xk GO SELECT TOP 10 PERCENT * FROM Course GO ㄚt 扚 ? ? h2=C蚅0! 17240671-13.3实训.sql [?灜? sql ?`?-2018.4.18 USE master GO --单元五 创建于管理数据库 --创建数据库Sale CREATE DATABASE sale ON PRIMARY (NAME=sale, FILENAME='C:\\sale.mdf', SIZE=4MB, MAXSIZE=20MB, FILEGROWTH=1MB ) LOG ON (NAME=sale_log, FILENAME='C:\\sale_log.ldf', SIZE=10MB, MAXSIZE=20MB, FILEGROWTH=1MB) GO --向数据库增加文件组UserGroup ALTER DATABASE sale ADD FILEGROUP UserGroup GO ALTER DATABASE sale ADD FILE (NAME='sale_data3', FILENAME='D:\\sale_data3.ndf', SIZE=5MB, MAXSIZE=10MB, FILEGROWTH=1MB ) TO FILEGROUP UserGroup GO sp_help sale GO USE master GO -- 单元六 创建于管理数据表 --创建客户表结构Customer CREATE TABLE Customer (CusNO nvarchar(3) NOT NULL, CusName nvarchar(10), Address nvarchar(20)NOT NULL, Tel nvarchar(20) NOT NULL) GO --创建场品表结构Product CREATE TABLE Product (ProNO nvarchar(5) NOT NULL, ProName nvarchar(20)NOT NULL, Price Decimal(8,2) NOT NULL, Stocks Decimal(6,0) NOT NULL) GO --创建入库表结构Proln CREATE TABLE Proln (InputDate DateTime NOT NULL, ProNo nvarchar(5) NOT NULL, Quantity Decimal(6,0) NOT NULL) GO --创建销售表结构Proout CREATE TABLE Proout (SaleDate DateTime NOT NULL, CusNo nvarchar(3) NOT NULL, ProNo nvarchar(5) NOT NULL, Quantity Decimal(6,0) NOT NULL, Amount Decimal(8,2)NOT NULL) GO --向已创建的表添加数据 INSERT Customer VALUES('001','杨婷','深圳','0755-22221111') INSERT Customer VALUES('002','陈萍','深圳','0755-22223333') INSERT Customer VALUES('003','李东','深圳','0755-22225555') INSERT Customer VALUES('004','叶合','广州','0755-22225555') INSERT Customer VALUES('005','谭新','广州','0755-22225555') Go INSERT Customer VALUES('0001','电视',3000.00,800) INSERT Customer VALUES('0002','空调',2000.00,500) INSERT Customer VALUES('0003','床',1000.00,300) INSERT Customer VALUES('0004','餐桌',1500.00,200) INSERT Customer VALUES('0005','音响',5000.00,600) INSERT Customer VALUES('0006','沙发',6000.00,100) Go INSERT Proln VALUES('2006-1-1','00001',10) INSERT Proln VALUES('2006-1-2','00002',5) INSERT Proln VALUES('2006-1-3','00001',5) INSERT Proln VALUES('2006-2-1','00003',10) INSERT Proln VALUES('2006-2-2','00001',10) INSERT Proln VALUES('2006-2-3','00003',20) INSERT Proln VALUES('2006-3-2','00001',10) INSERT Proln VALUES('2006-3-2','00004',30) INSERT Proln VALUES('2006-3-3','00003',20) Go INSERT ProOut VALUES('2006-1-1','001','00001',10) INSERT ProOut VALUES('2006-1-2','001','00002',5) INSERT ProOut VALUES('2006-1-3','002','00001',5) INSERT ProOut VALUES('2006-2-1','002','00003',10) INSERT ProOut VALUES('2006-2-2','001','00001',10) INSERT ProOut VALUES('2006-2-3','001','00003',20) INSERT ProOut VALUES('2006-3-2','003','00001',10) INSERT ProOut VALUES('2006-3-2','003','00004',30) INSERT ProOut VALUES('2006-3-3','002','00003',20) Go --单元七 实施数据完整性(约束) --使用ALTER TABLE 语句为已经创建的表添加主键约束、外键约束 --主键 ALTER TABLE Customer ADD CONSTRAINT PK_Customer PRIMARY KEY(CusNo) GO ALTER TABLE Product ADD CONSTRAINT PK_Product PRIMARY KEY(ProNo) GO --外键 ALTER TABLE Proout ADD CONSTRAINT FK_Proout_Product FOREIGN KEY(ProNo) REFERENCES Product(ProNo) GO ALTER TABLE Proout ADD CONSTRAINT FK_Proout_Customer FOREIGN KEY(CusNo) REFERENCES Customer(Customer) GO ALTER TABLE Proln ADD CONSTRAINT FK_Proln_Product FOREIGN KEY(ProNo) REFERENCES Product(ProNo) GO --约束客户表Customer的CosNo的列值长度为3,产品表Product 的ProNo 列值长度为5 ALTER TABLE Coustomer ADD CONSTRAINT CK_Customer_CusNo CHECK (CusNo like '[0-9][0-9][0-9]') GO ALTER TABLE Product ADD CONSTRAINT CK_Product_ProNo CHECK(ProNo like'[0-9][0-9][0-9][0-9][0-9]') GO --对产品表Product 的Stocks列、Price列、入库表Proln的Quanity列、销售表ProOut 的Quanity --列值进行约束,使其值大于0 ALTER TABLE Product ADD CONSTRAINT CK_Product_Stock CHECK(Stock>0) GO ALTER TABLE Product ADD CONSTRAINT CK_Product_Price CHECK(Price>0) GO ALTER TABLE Proln ADD CONSTRAINT CK_Proln_Quantity CHECK (Quantity>0) GO ALTER TABLE ProOut ADD CONSTRAINT CK_ProOut_Quantity CHECK(Quantity>0) GO --对销售表ProOut的SaleDate 列进行约束,当不输入值时,系统默认其值为系统当前日期 CREATE DEFAULT Today AS GETDATEA() GO /*ALTER TABLE ProOut ADD CONSTRAINT DF_ProOut_SaleDate DEFAULT('当前日期')FOR Date GO*/ --单元八 索引 --用户按照CusName查询客户信息,希望提高查询速度 CREATE UNIQUE INDEX IX_CusName ON Customer(CusName) GO --用户按照ProName查询产品信息,希望提高查询速度 CREATE UNIQUE INDEX IX_ProName ON Product(ProName) GO --用户按照SaleDate查询产品信息,希望提高查询速度 CREATE UNIQUE INDEX IX_SaleDate ON ProOut(SaleDate) GO --单元九 语言编程基础 --计算有多少种产品(假设为x),然后显示一条信息:共有X种产品 DECLARE @X int SET @X =(SELECT COUNT (*) FROM Product ) PRINT '共有'+convert (char(2),@x)+'种产品。' GO --编写计算n!(n=20)的程序,并显示结果。 DECLARE @X int,@product int SELECT @X=1,@product=1 WHILE @X<=20 BEGIN SELECT @X=@X+1 SELECT @product=@product*@X END SELECT '1*2*3*......*20的积'=@product GO --单元十 创建于管理视图 --创建视图V_Sale1,并显示销售日期、客户编号、客户姓名、产品编号、产品名称、单价 --销售数量、销售金额 CREATE VIEW V_Sale1 AS SELECT SaleDate,Customer.CusNO,CusName,Product.ProNO,ProName,Price,Proout.Quantity, SM=(Price *Proout.Quantity) FROM Customer ,Product,Proln,Proout WHERE Customer.CusNO=Proout.CusNo AND Product.ProNO=Proln.ProNo AND Product.ProNO=Proout.ProNo AND Proout.Quantity=Proln.Quantity GO --创建视图V-Sale2,统计每种产品的销售数量和销售金额。统计结果包括产品编号、 --产品名称、单价、销售数量和销售金额 CREATE VIEW V_Sale2 AS SELECT Product.ProNO ,ProName,Price,Proout.Quantity ,SM=(Price *Proout.Quantity) FROM Product ,Proout ,Proln GROUP BY ProName GO --创建视图V_Sale3,统计销售金额在10万以下的产品信息。 CREATE VIEW V_Sale3 AS SELECT Product.ProNO ,Product.ProName FROM Product ,Proout WHERE Product.ProNO=Proout.ProNo GROUP BY Product.ProNO,ProName HAVING SUM (Price*Quantity)<100000 GO --单元十一 创建管理存储过程 --创建存储过程P_Sale1,统计每种产品的销售数量和销售金额 CREATE PROCEDURE P_Sale1 AS SELECT Product.ProNO,ProName ,Price ,SUM(Quantity),SM=SUM(Price*Quantity) FROM Proout,Product WHERE Product.ProNO=Proout.ProNo GROUP BY Product .ProNO,ProName,Price GO --创建存储过程P_Sale2,能够根据指定客户统计,汇总该客户购买每种产品的数量和花费金额 CREATE PROCEDURE P_Sale2 @CusNo nvarchar(3) AS SELECT Product.ProNO,ProName,Price ,SUM(Quantity),SUM(Price*Quantity) FROM Product,Proout WHERE CusNO=@CusNO AND Product.ProNO=Proout.ProNo GROUP BY Product .ProNO,ProName ,Price GO --创建存储过程P_Sale3,能够根据指定的产品编号和日期,以输出参数的形式得到该产品的销售金额 CREATE PROCEDURE P_Sale3 @ProNo nvarchar(5),@SaleDate DateTime,@MONEY Decimal(8,2)OUTPUT AS SET @MONEY=( SELECT SUM(Price*Quantity) FROM Proout,Product WHERE Product.ProNO=Proout.ProNo AND Product.ProNO=@ProNo AND SaleDate =@SaleDate GROUP BY Product .ProNO,ProName ,Price ) PRINT @MONEY GO --单元十二 触发器 --创建触发器,实现即时更新每种产品的库存数量。 CREATE TRIGGER UPDATE_ProNo_Stocks_TRIGGER ON Product FOR UPDATE AS PRINT'已即时更新每种产品的库存数量' GO --使用IF UPDATE(column)尽可能优化上题的触发器,以提高系统效率 ALTER TRIGGER UPDATE_ProNo_Stocks_TRIGGER ON Product FOR UPDATE AS IF UPDATE (ProNo) PRINT '已更新' GO --单元十三 游标 --创建存储过程P_SelProduct,逐行显示产品销售信息,内容包括编号、产品名称、销售日期、 --销售数量、销售金额、要求显示格式如下: --产品编号 产品名称 销售日期 销售数量 销售金额 --00001 电视 2006-1-1 10 30000 --产品编号 产品名称 销售日期 销售数量 销售金额 --00002 空调 2006-1-2 5 10000 CREATE PROCEDURE P_SelProduct AS DECLARE @ProNo NVARCHAR(5),@ProName nvarchar(20), @SaleDate DateTime,@Quantity Decimal(6,0), @SM Decimal(8,2) DECLARE CRS CURSOR FOR SELECT Product.ProNO,ProName,SaleDate,Quantity,SM=(Price*Quantity) FROM Product ,Proout WHERE Product .ProNO=Proout.ProNo ORDER BY SaleDate OPEN CRS FETCH NEXT FROM CRS INTO @ProNo,@ProName , @SaleDate,@Quantity ,@SM WHILE @@FETCH_STATUS =0 BEGIN PRINT '产品编号 产品名称 销售日期 销售数量 销售金额' PRINT @ProNo+' '+@ProName+' '+STR(YEAR(@SaleDate))+'-'+STR(MONTH(@SaleDate)) +'-'+STR(DAY(@SaleDate))+' '+@Quantity+' '+@SM+' ' FETCH NEXT FROM CRS INTO @ProNo,@ProName , @SaleDate,@Quantity , @SM END CLOSE CRS DEALLOCATE CRS t 扚 ]$ ]$ 晹轺褻蚅0! 17240671-14.2实训.sql [?灜? sql ?|--2018.4.18 USE master GO --单元五 创建于管理数据库 --创建数据库Sale CREATE DATABASE sale ON PRIMARY (NAME=sale, FILENAME='C:\\sale.mdf', SIZE=4MB, MAXSIZE=20MB, FILEGROWTH=1MB ) LOG ON (NAME=sale_log, FILENAME='C:\\sale_log.ldf', SIZE=10MB, MAXSIZE=20MB, FILEGROWTH=1MB) GO --向数据库增加文件组UserGroup ALTER DATABASE sale ADD FILEGROUP UserGroup GO ALTER DATABASE sale ADD FILE (NAME='sale_data3', FILENAME='D:\\sale_data3.ndf', SIZE=5MB, MAXSIZE=10MB, FILEGROWTH=1MB ) TO FILEGROUP UserGroup GO sp_help sale GO USE master GO -- 单元六 创建于管理数据表 --创建客户表结构Customer CREATE TABLE Customer (CusNO nvarchar(3) NOT NULL, CusName nvarchar(10), Address nvarchar(20)NOT NULL, Tel nvarchar(20) NOT NULL) GO --创建场品表结构Product CREATE TABLE Product (ProNO nvarchar(5) NOT NULL, ProName nvarchar(20)NOT NULL, Price Decimal(8,2) NOT NULL, Stocks Decimal(6,0) NOT NULL) GO --创建入库表结构Proln CREATE TABLE Proln (InputDate DateTime NOT NULL, ProNo nvarchar(5) NOT NULL, Quantity Decimal(6,0) NOT NULL) GO --创建销售表结构Proout CREATE TABLE Proout (SaleDate DateTime NOT NULL, CusNo nvarchar(3) NOT NULL, ProNo nvarchar(5) NOT NULL, Quantity Decimal(6,0) NOT NULL, Amount Decimal(8,2)NOT NULL) GO --向已创建的表添加数据 INSERT Customer VALUES('001','杨婷','深圳','0755-22221111') INSERT Customer VALUES('002','陈萍','深圳','0755-22223333') INSERT Customer VALUES('003','李东','深圳','0755-22225555') INSERT Customer VALUES('004','叶合','广州','0755-22227777') INSERT Customer VALUES('005','谭新','广州','0755-22229999') Go INSERT Product VALUES('00001','电视',3000.00,800) INSERT Customer VALUES('00002','空调',2000.00,500) INSERT Customer VALUES('00003','床',1000.00,300) INSERT Customer VALUES('00004','餐桌',1500.00,200) INSERT Customer VALUES('00005','音响',5000.00,600) INSERT Customer VALUES('00006','沙发',6000.00,100) Go INSERT Proln VALUES('2006-1-1','00001',10) INSERT Proln VALUES('2006-1-1','00002',5) INSERT Proln VALUES('2006-1-2','00001',5) INSERT Proln VALUES('2006-1-2','00003',10) INSERT Proln VALUES('2006-1-3','00001',10) INSERT Proln VALUES('2006-2-1','00003',20) INSERT Proln VALUES('2006-2-2','00001',10) INSERT Proln VALUES('2006-2-3','00004',30) INSERT Proln VALUES('2006-3-3','00003',20) Go INSERT ProOut VALUES('2006-1-1','001','00001',10) INSERT ProOut VALUES('2006-1-2','001','00002',5) INSERT ProOut VALUES('2006-1-3','002','00001',5) INSERT ProOut VALUES('2006-2-1','002','00003',10) INSERT ProOut VALUES('2006-2-2','001','00001',10) INSERT ProOut VALUES('2006-2-3','001','00003',20) INSERT ProOut VALUES('2006-3-2','003','00001',10) INSERT ProOut VALUES('2006-3-2','003','00004',30) INSERT ProOut VALUES('2006-3-3','002','00003',20) Go --单元七 实施数据完整性(约束) --使用ALTER TABLE 语句为已经创建的表添加主键约束、外键约束 --主键 ALTER TABLE Customer ADD CONSTRAINT PK_Customer PRIMARY KEY(CusNo) GO ALTER TABLE Product ADD CONSTRAINT PK_Product PRIMARY KEY(ProNo) GO --外键 ALTER TABLE Proout ADD CONSTRAINT FK_Proout_Product FOREIGN KEY(ProNo) REFERENCES Product(ProNo) GO ALTER TABLE Proout ADD CONSTRAINT FK_Proout_Customer FOREIGN KEY(CusNo) REFERENCES Customer(Customer) GO ALTER TABLE Proln ADD CONSTRAINT FK_Proln_Product FOREIGN KEY(ProNo) REFERENCES Product(ProNo) GO --约束客户表Customer的CosNo的列值长度为3,产品表Product 的ProNo 列值长度为5 ALTER TABLE Coustomer ADD CONSTRAINT CK_Customer_CusNo CHECK (CusNo like '[0-9][0-9][0-9]') GO ALTER TABLE Product ADD CONSTRAINT CK_Product_ProNo CHECK(ProNo like'[0-9][0-9][0-9][0-9][0-9]') GO --对产品表Product 的Stocks列、Price列、入库表Proln的Quanity列、销售表ProOut 的Quanity --列值进行约束,使其值大于0 ALTER TABLE Product ADD CONSTRAINT CK_Product_Stock CHECK(Stock>0) GO ALTER TABLE Product ADD CONSTRAINT CK_Product_Price CHECK(Price>0) GO ALTER TABLE Proln ADD CONSTRAINT CK_Proln_Quantity CHECK (Quantity>0) GO ALTER TABLE ProOut ADD CONSTRAINT CK_ProOut_Quantity CHECK(Quantity>0) GO --对销售表ProOut的SaleDate 列进行约束,当不输入值时,系统默认其值为系统当前日期 CREATE DEFAULT Today AS GETDATEA() GO /*ALTER TABLE ProOut ADD CONSTRAINT DF_ProOut_SaleDate DEFAULT('当前日期')FOR Date GO*/ --单元八 索引 --用户按照CusName查询客户信息,希望提高查询速度 CREATE UNIQUE INDEX IX_CusName ON Customer(CusName) GO --用户按照ProName查询产品信息,希望提高查询速度 CREATE UNIQUE INDEX IX_ProName ON Product(ProName) GO --用户按照SaleDate查询产品信息,希望提高查询速度 CREATE UNIQUE INDEX IX_SaleDate ON ProOut(SaleDate) GO --单元九 语言编程基础 --计算有多少种产品(假设为x),然后显示一条信息:共有X种产品 DECLARE @X int SET @X =(SELECT COUNT (*) FROM Product ) PRINT '共有'+convert (char(2),@x)+'种产品。' GO --编写计算n!(n=20)的程序,并显示结果。 DECLARE @X int,@product int SELECT @X=1,@product=1 WHILE @X<=20 BEGIN SELECT @X=@X+1 SELECT @product=@product*@X END SELECT '1*2*3*......*20的积'=@product GO --单元十 创建于管理视图 --创建视图V_Sale1,并显示销售日期、客户编号、客户姓名、产品编号、产品名称、单价 --销售数量、销售金额 CREATE VIEW V_Sale1 AS SELECT SaleDate,Customer.CusNO,CusName,Product.ProNO,ProName,Price,Proout.Quantity, SM=(Price *Proout.Quantity) FROM Customer ,Product,Proln,Proout WHERE Customer.CusNO=Proout.CusNo AND Product.ProNO=Proln.ProNo AND Product.ProNO=Proout.ProNo AND Proout.Quantity=Proln.Quantity GO --创建视图V-Sale2,统计每种产品的销售数量和销售金额。统计结果包括产品编号、 --产品名称、单价、销售数量和销售金额 CREATE VIEW V_Sale2 AS SELECT Product.ProNO ,ProName,Price,Proout.Quantity ,SM=(Price *Proout.Quantity) FROM Product ,Proout ,Proln GROUP BY ProName GO --创建视图V_Sale3,统计销售金额在10万以下的产品信息。 CREATE VIEW V_Sale3 AS SELECT Product.ProNO ,Product.ProName FROM Product ,Proout WHERE Product.ProNO=Proout.ProNo GROUP BY Product.ProNO,ProName HAVING SUM (Price*Quantity)<100000 GO --单元十一 创建管理存储过程 --创建存储过程P_Sale1,统计每种产品的销售数量和销售金额 CREATE PROCEDURE P_Sale1 AS SELECT Product.ProNO,ProName ,Price ,SUM(Quantity),SM=SUM(Price*Quantity) FROM Proout,Product WHERE Product.ProNO=Proout.ProNo GROUP BY Product .ProNO,ProName,Price GO --创建存储过程P_Sale2,能够根据指定客户统计,汇总该客户购买每种产品的数量和花费金额 CREATE PROCEDURE P_Sale2 @CusNo nvarchar(3) AS SELECT Product.ProNO,ProName,Price ,SUM(Quantity),SUM(Price*Quantity) FROM Product,Proout WHERE CusNO=@CusNO AND Product.ProNO=Proout.ProNo GROUP BY Product .ProNO,ProName ,Price GO --创建存储过程P_Sale3,能够根据指定的产品编号和日期,以输出参数的形式得到该产品的销售金额 CREATE PROCEDURE P_Sale3 @ProNo nvarchar(5),@SaleDate DateTime,@MONEY Decimal(8,2)OUTPUT AS SET @MONEY=( SELECT SUM(Price*Quantity) FROM Proout,Product WHERE Product.ProNO=Proout.ProNo AND Product.ProNO=@ProNo AND SaleDate =@SaleDate GROUP BY Product .ProNO,ProName ,Price ) PRINT @MONEY GO --单元十二 触发器 --创建触发器,实现即时更新每种产品的库存数量。 CREATE TRIGGER UPDATE_ProNo_Stocks_TRIGGER ON Product FOR UPDATE AS PRINT'已即时更新每种产品的库存数量' GO --使用IF UPDATE(column)尽可能优化上题的触发器,以提高系统效率 ALTER TRIGGER UPDATE_ProNo_Stocks_TRIGGER ON Product FOR UPDATE AS IF UPDATE (ProNo) PRINT '已更新' GO --单元十三 游标 --创建存储过程P_SelProduct,逐行显示产品销售信息,内容包括编号、产品名称、销售日期、 --销售数量、销售金额、要求显示格式如下: --产品编号 产品名称 销售日期 销售数量 销售金额 --00001 电视 2006-1-1 10 30000 --产品编号 产品名称 销售日期 销售数量 销售金额 --00002 空调 2006-1-2 5 10000 CREATE PROCEDURE P_SelProduct AS DECLARE @ProNo NVARCHAR(5),@ProName nvarchar(20), @SaleDate DateTime,@Quantity Decimal(6,0), @SM Decimal(8,2) DECLARE CRS CURSOR FOR SELECT Product.ProNO,ProName,SaleDate,Quantity,SM=(Price*Quantity) FROM Product ,Proout WHERE Product .ProNO=Proout.ProNo ORDER BY SaleDate OPEN CRS FETCH NEXT FROM CRS INTO @ProNo,@ProName , @SaleDate,@Quantity ,@SM WHILE @@FETCH_STATUS =0 BEGIN PRINT '产品编号 产品名称 销售日期 销售数量 销售金额' PRINT @ProNo+' '+@ProName+' '+STR(YEAR(@SaleDate))+'-'+STR(MONTH(@SaleDate)) +'-'+STR(DAY(@SaleDate))+' '+@Quantity+' '+@SM+' ' FETCH NEXT FROM CRS INTO @ProNo,@ProName , @SaleDate,@Quantity , @SM END CLOSE CRS DEALLOCATE CRS GO --单元十四 事务与锁 --1、一般情况下,只有当产品有足够的库存量时才允许销售该产品。创建一事务,实现当向Proout(销售)表插入新的数据行时,如果 --Stock(库存数)大于Quantity(销售数量),则允许销售,否则拒绝销售。 CREATE PROCEDURE P1 @SaleDate DateTime , @CusNo nvarchar(3), @ProNo nvarchar(5), @Quantity Decimal(6,0) AS BEGIN TRANSACTION INSERT Proout(SaleDate,CusNo,ProNo,Quantity) VALUES(@SaleDate ,@CusNo ,@ProNo,@Quantity ) DECLARE @CountNum INT SET @CountNum =(SELECT Stocks FROM Product WHERE ProNo=@ProNo)-(SELECT SUM(Quantity) FROM Proout WHERE ProNo=@ProNo) IF @CountNum<0 BEGIN ROLLBACK TRANSACTION PRINT '库存数量小于销售数量,拒绝销售。' END ELSE BEGIN COMMIT TRANSACTION PRINT '销售成功!' END GO --测试 INSERT INTO Proout VALUES('2016-6-1','002','000001',900) GO --2、不用触发器,用事务的方式实现:当产品入库和销售时能保证库存数量的准确性。谈谈你对触发器实现和使用事务实现的理解 t ? + + G鹙坺BwL0 17240671-2.sql 饌? --2018年3月14日 USE Xk GO --查询“00000001”同学是否报了“003”课程 SELECT * From StuCou where StuNo='00000001' and CouNo='003' GO --查询报名人数在15-40范围内的课程信息 SELECT * FROM Course WHERE WillNum>=15 AND WillNum<=40 GO --Between...and... SELECT * FROM Course WHERE WillNum BETWEEN 15 AND 40 GO --查询课程编号分别为"004"、"007"、"013"的课程信息(理解or) SELECT * FROM Course WHERE CouNo='004' or CouNo='007' or CouNo='013' GO --in的用法 SELECT * FROM Course WHERE CouNo IN ('004','007','013') GO --查询课程编号分别不为"004"、"007"、"013"的课程信息(not) SELECT * FROM Course WHERE CouNo NOT IN ('004','007','013') GO --查询课程信息、报名人数占限选人数之比(表达式作为列) SELECT * , WillNum/LimitNum AS '报名人数占限选人数之比' FROM Course GO --补充问题:小数点只保留2位(convert()函数、cast()函数) SELECT * ,convert (decimal(4,2),WillNum/LimitNum) AS '报名人数占限选人数之比' FROM Course GO SELECT * ,cast (WillNum/LimitNum as decimal(4,2)) AS '报名人数占限选人数之比' FROM Course GO --查询课程信息、报名人数占限选人数之比(升ASC、降DESC 序) SELECT * ,cast (WillNum/LimitNum as decimal(4,2)) AS '报名人数占限选人数之比' FROM Course ORDER BY WillNum DESC GO --查询课程信息、报名人数占限选人数之比以降序排列并查询前10行(前10%) SELECT top 10 * ,cast (WillNum/LimitNum as decimal(4,2)) AS '报名人数占限选人数之比' FROM Course ORDER BY WillNum DESC GO --查询选修课的任课教师名、课程号、课程名。要求教师名降序排列,教师名相同时,按课程号的升序排列 SELECT teacher as '教师名',CouNo as '课程号',CouName as '教程名' FROM Course ORDER BY Teacher DESC,CouNo ASC GO --查询课程信息,要求查询结果为(在查询结果增加字符串) SELECT '课程编码'=CouNO,'课程名称为:','课程名称'=CouName FROM Course GO --查询带有‘制作’课程 SELECT '课程编码'=CouNO,'课程名称为:','课程名称'=CouName FROM Course WHERE CouName LIKE '%制作%' GO -2018年3月17日 USE Xk GO 查询选课表随机数无值的数据行 SELECT * FROM StuCou WHERE RandomNum IS NULL GO SELECT * FROM Course GO --查看选课表有多少门课程 --COUNT函数 SELECT COUNT(*)AS '课程总门数' FROM Course GO SELECT COUNT(CouNo)AS '课程总门数' FROM Course GO SELECT COUNT(*)FROM StuCou GO SELECT COUNT(RandomNum) FROM StuCou GO SELECT COUNT(Kind)AS '课程总门数' FROM Course GO --t ? ? ? 广~燪uL0 17240671-3.sql 餷wY--2018-3-21 USE Xk GO --1.平均 SELECT AVG(*)FROM Cours GO --2 SELECT Coure(*)FROM Student GO --3 --4 SELECT COUNT(DITINCT Kind) FROM Course FROM Course GO --5按照课程类别分组统计各类课程的门 SELECT Kind AS '课程种类',COUNT(Kind) AS '该种类的课程' FROM Course GROUP BY Kind GO --6 SELECT MIN(willNum) as'最报名人',MAX(willNum) as '最多报名人' FROM Course WHERE willNum >15 GROUP By Kind --7 SELECT Kind,AVG(WillNum) FROM Course WHERE WillNum>15 GROUP BY Kind HAVING AVG(WillNum)>30 GO --8 SELECT Kind,AVG(WillNum) FROM Coure WHERE Kind IN('管理')OR Kind GROUP BY ALL Kind GO SELECT * FROM Course COMPUTE By DepartNo COMPUTE AVG(WillNum) By DepartNo GO甬t ? O O 泎蝼P|L0 17240671-4.sql 餺9?-2018年3月28日 USE Xk GO --4, SELECT Student.StuNo,StuName,Course,CouNo,CouName,Credit FROM Student Course,StuCou WEHERE Student.StuNo = StuCou.StuNo AND COurse.CouNo.CouNo ORDER BY CouName,Student.StuNo GO --方法2 SELECT Student.StuNo,StuName,Course,CouNo,CouName,Credit FROM Student JOIN StuCou ON Student.StuNo = StuCou.StuNo JOIN Course ON Course CouNo = StuCou.StuNo ORDER BY CouName,Student.StuNo GO /*--查询同学报名‘计算机应用工工程系’选修课程的情况,显示信息包括:学号,姓名,课程编号,课程名,教师,上课时间,按照课程编号排序, 课程编号相同时,按照学号排序*/ SELECT Student.StuNo,StuName,CouNo,CouName,Teacher,ScoolTime FROM Student,Course,StuCou WHERE Student.StuNo=StuCou.StuNo AND Course=StuCou.CouNo AND DepartName='计算机工程系' AND Department.DepartNo=Course.DepartNo ORDER BY Course.CouNo,Student.StuNo GO --修改使用别名完成上题 SELECT Student.StuNo,StuName,CouNo,CouName,Teacher,ScoolTime FROM Student JOIN StuCou SC ON S.StuNo = SC.StuNo JOIN Course C ON C.CouNo = SC.CouNo JOIN Department D ON D.DepartNo=C.DepartNo WHERE DepartName='计算机工程系' ORDER BY C.CouNo,S.StuNo GO --练一练,查询各班同学的信息,要求显示,班级编号,班级名称,学号,姓名,按照班级编号排序,当班级编号相同时,按照学号排序 --课本73页[2.35]查询每个班级可以选修的,不是自己所在系部开设的选修课程信息,显示信息包括班级,课程名,课程种类, --学分,老师,上课时间和报名人数。 SELECT '班级编号'=ClassNo'班级名称','课程名'=CouName,'课程种类'=Kind,'学分'=Credit,'老师'=Teacher,'上课时间'=ScoolTime, '报名人数'=WillNum FROM Class,Course WHERE Class.DepartNo<>Course.DEpartNo GO --课本73页[2.36] --查询课程类别相同但开课系部不同的课程信息,要求显示课程编号,课程名称,课程类别,系部编号,按照课程编号升序排序 SELECT '课程编号'=C1.CouNo,'课程名称'=C1.CouName,'课程类别'=C1.Kind,'系部编号'=C1.DepartNo FROM Course C1,Course C2 WHERE C1,Kind=C2.Kind AND C1.DepartNo<>C2.DEpartNo ORDER BY 课程编号 GO --外连接 --观察如下查询数据 --查询课程信息 SELECT CouNo,CouName,WillNum FROM Course ORDER BY CouNo GO --查询所有同学报名选修课的情况(包括有报名和没人报名),显示学号,姓名,课程号,课程名。 SELECT '学号'=CouNo,'姓名'=StuName,'课程号'=CouNo,'课程名'=CouName FROM Student,Course,StuCou WHERE Course.CouNo=StuCou.CouNo GO --丢失了没人报名的019课程,使用外连接信息丢失的问题 SELECT '学号'=StuNo,'姓名'=StuName,'课程号'=CouNo,'课程名'=CouName FROM Course LEFT JOIN StuCou /*左外连接,解决的是JOIN左面的表丢失的数据*/ ON Course.CouNo=StuCou.StuNo ORDER BY Course.CouNo GO --查询选修表信息 SELECT CouNo FROM StuCou ORDER BY CouNo GO`}t ? K K ?n⑾P凩0 17240671-5.sql 餹鱧--2018年4月4日 USE Xk GO --1,学号为'00000025'的学生第一志愿报名选修"001"课程.请在数据库进行处理.(增加数据进StuCou表) SELECT * FROM StuCou WHERE StuNo='00000025' GO INSERT StuCou(StuNo,CouNo,WillOrder,State) VALUES('00000025','001',1,'报名') GO --2,删除学号为'00000025'的学生的选修课报名信息。 DELETE StuCou WHERE StuNo='00000025' AND CouNo='01' GO UPDATE Course SET WillNum=WillNum-1 WHERE CouNo='001' --3,将"00多媒体"班的"杜晓静"的名字修改为"杜小静"。 UPDATE Student SET StuName='杜小静' FROM Student.Class WHERE StuName='杜晓静' AND ClassName='00多媒体' AND Student.ClassNo=Class.ClassNo --4,"00电子商务"班的"林斌"申请将已选修的"网络信息检索原理与技术"课程修改为"Linux操作系统". UPDATE StuCou SET CouNo = (SELECT CouNo FROM Course WHERE CouName = 'Linux操作系统') FROM StuCou,Class,Student,Course WHERE Class.Class Student.StuName = '林斌' AND CouName = '网络信息检索原理与技术' AND Class.ClassNo = Student.ClassNo AND Student.StuNo = StuCou.StuNo AND Name = '00电子商务' AND Course.CouNo = StuCou.CouNo 见t ? ? ? 剮L0 17240671-6-2.sql ?? USE master GO CREATE DATABASE Sale ON (NAME=Sale, FILENAME='E:\\Sale.mdf', SIZE=4, MAXSIZE=10, FILEGROWTH=1) LOG ON (NAME=Sale_log, FILENAME='F:\\Sale_log.ldf', SIZE=2, MAXSIZE=10, FILEGROWTH=1) GO USE Sale GO ALTER DATABASE Sale ADD FILEGROUP UserGroup GO USE master GO ALTER DATABASE Sale ADD FILE (NAME=Sale, FILENAME='E:\\Sale2.ndf', SIZE=5MB, MAXSIZE=10MB, FILEGROWTH=1MB) TO FILEGROWOUP UserGroup GO SP_helpdb Sale GO?t ? ? ? ╡?WP扡0 17240671-7-1sql 餋嘵--2018年4月18日第七周 USE Xk GO ALTER DATABASE Xk ADD FILEGROUP TableGroup GO sp_helpfilegroup TableGroup GO USE Xk GO --创建班级信息表Class CREATE TABLE Class1 (ClassNo nvarchar (8) NOT NULL, ClassName nvarchar (20) NOT NULL, DepartNo nvarchar (2) NOT NULL) GO --创建学生信息表Student CREATE TABLE Student1 (StuNo nvarchar (8) NOT NULL, StuName nvarchar (10) NOT NULL, Pwd nvarchar (8) NOT NULL, ClassNo nvarchar (8) NOT NULL) GO --创建学生选课表StuCou CREATE TABLE StuCou1 (StuNo nvarchar (8) NOT NULL, CouNo nvarchar (3) NOT NULL, WillOrder smallint NOT NULL, State nvarchar (2) NOT NULL, RandomNum nvarchar (50) NULL) GO USE Xk GO ALTER TABLE Student ADD birthday datetime null,bz nvarchar(20) null GO USE Xk GO ALTER TABLE Student DROP COLUMN birthday GO USE Xk GO ALTER TABLE Student ALTER COLUMN bz nvarchar(30) null GO USE Xk GO sp_rename 'Student.bz','StuBz','COLUMN' GO 鮰 ? ? ? E諹wE汱0 17240671-7-2.sql ?_2 USE master GO CREATE DATABASE Sale ON (NAME=Sale, FILENAME='C:\\Sale.mdf', SIZE=4, MAXSIZE=10, FILEGROWTH=1) LOG ON (NAME=Sale_log, FILENAME='C:\\Sale_log.ldf', SIZE=2, MAXSIZE=10, FILEGROWTH=1) GO USE Sale CREATE TABLE Customer (CusNo nvarchar(3) NOT NULL, CusName nvarchar(10) NOT NULL, Address nvarchar(20) NULL, Tel nvarchar(20) NULL) GO CREATE TABLE Product (ProNo nvarchar(5) NOT NULL, ProName nvarchar(20) NOT NULL, Price Decimal(8,2) NOT NULL, Stocks Decimal(8,0) NOT NULL) GO CREATE TABLE Proln (InputDate DateTime NOT NULL, ProNo nvarchar(5)NOT NULL, Quantity Decimal(6,0)NOT NULL) GO CREATE TABLE ProOut (SaleDate DateTime NOT NULL, CusNo nvarchar(3)NOT NULL, ProNo nvarchar(5)NOT NULL, Quantity Decimal(6,0)NOT NULL) GO INSERT Customer VALUES ('001','杨婷','深圳','0755-22221111') INSERT Customer VALUES ('002','陈萍','深圳','0755-22223333') INSERT Customer VALUES ('003','李东','深圳','0755-22225555') INSERT Customer VALUES ('004','叶合','广州','0755-22225555') INSERT Customer VALUES ('005','谭新','广州','0755-22225555') GO INSERT Proln VALUES ('2006-1-1','00001','10') INSERT Proln VALUES ('2006-1-2','00002','5') INSERT Proln VALUES ('2006-1-3','00001','5') INSERT Proln VALUES ('2006-2-1','00003','10') INSERT Proln VALUES ('2006-2-2','00001','10') INSERT Proln VALUES ('2006-2-3','00003','10') INSERT Proln VALUES ('2006-3-2','00001','10') INSERT Proln VALUES ('2006-3-2','00004','30') INSERT Proln VALUES ('2006-3-3','00003','20') GO --添加主键约束,外键约束 ALTER TABLE Customer ADD CONSTRAINT PK_Customer PRIMARY KEY(CusNo) GO ALTER TABLE Product ADD CONSTRAINT PK_Product PRIMARY KEY(ProNo) GO ALTER TABLE Proln ADD CONSTRAINT PK_Proln PRIMARY KEY(ProNo) GO ALTER TABLE ProOut ADD CONSTRAINT PK_ProOut PRIMARY KEY(CusNo,ProNo) GO --运用检查约束 ALTER TABLE Product ADD CONSTRAINT CK_Stock CHECK(Stock>0) ALTER TABLE Product ADD CONSTRAINT CK_Price CHECK(Price>0) ALTER TABLE Proln ADD CONSTRAINT CK_Quantity CHECK(Quantity>0) ALTER TABLE ProOut ADD CONSTRAINT CK_Quantity CHECK(Quantity>0) GO --运用默认约束 ALTER TABLE ProOut ADD CONSTRAINT DF_ProOut_Saledate DEFAULT('当前日期')FOR Date GO?t ? ? ? €猳?Q㎜0 17240671.10.1.sql 皝?--2018-4-9日 编程基础 SELECT ClassNo From Xk..Class GO SELECT CLassNo FROM Xk.dbo.Class GO --T_sql语法元素:标识符(两种),局部变量,全局变量,数据类型 /* */ SELECT @@SERVERNAME SELECT @@MAX_CONNECTIONS SELECT @@LANGUAGE SELECT @@VERSION SELECT * FROM Xk..Student GO SELECT * FROM Class GO USE Xk SELECT * FROM Xk..Student GO USE Xk CREATE VIEW V TEST AS SELECT * FROM Student GO USE Xk GO CREATE VIEW V TEST AS SELECT * FROM Student GO DECLARE @iNUM INT SET @iNUM=5 PRINI @INUM --显示Course表有多少类课程? SELECT COUNT(DISTINCT Kind)FROM Course GO --显示Course表有多少类课程,要求将结果保存到一个局部变量,并显示出来。 DECLARE @KindCount Tinyint SET @KindCount=(SELECT COUNT (DISTINCT Kind)FROM Course) PRINT @KindCount GO DECLARE @KindCount Tinyint SET @KindCount=(SELECT COUNT (DISTINCT Kind)FROM Course) PRINT 'Course表有'+CONVERT (VARCHAR(3),@KindCount)+'类课程' GO --练一练:1,编写计算1+2+3+10000的和,并显示计算结果。 DECLARE @i int,@sum=0 SELECT @i=1,@sum=0 WHILE @i<=10000 BEGIN SELECT @sum=@sum+@i SELECT @i=@i+1 END SELECT'1+2+3+4+......+10000的和'=@sum GO --练一练:2,编写计算20!,并显示计算结果。 --练一练:3,@iNum1,@iNum2为两个整型变量,值分为76,90,编程显示两个变量的较大者。 DECLARE @iNum1 int,@iNum2 int SELECT @iNum1=76,@iNum2=90 IF(@iNum1>@iNum2) PRINT @iNum1 ELSE PRINT @iNum2 GO]謙 ? ? ? ;砝blO獿0 17240671.10.2.sql 餹M--2018-05-11 DECLARE @iNum1 int,@iNum2 int SELECT @iNum1=79,@iNum2=90 if(@iNum1>@iNum2) PRINT @iNum1 else PRINT @iNum2 GO USE Xk GO SELECT '课程类别'=Kind,'分类的课程类别'= CASE Kind WHEN '工程技术'THEN'工科类课程' WHEN '人文'THEN'人文类课程' WHEN '信息技术'THEN '信息技术类课程' ELSE '其他类课程' END,'课程名称'=CouName,'报名人数'=WillNum FROM Course ORDER BY Kind,WillNum COMPUTE AVG(WillNum)BY Kind GO --问题9.13校长生日1979/12/23,使用日期函数显示校长年龄 SELECT '年龄'=DATEDIFF(YY,'1979/12/23',GETDATE()) GO --如果一个人的出生日期为1922/2/23,计算并显示目前总天数 SELECT '天数'=DATEDIFF(DD,'1922/2/23',GETDATE()) GO --问题9.26 CREATE FUNCTION CalcRemainNum (@X decimal(6,0),@Y decimal(6,0)) RETURNS decimal(6,0) AS BEGIN RETURN(@X-@Y) END GO ALTER TABLE Course ADD RemainNum AS dbo.CalcRemainNum(LimitNum,ChooseNum) GO SELECT *FROM Course GO  ? c c ?/fP癓0 17240671.10.4.sql 饃XK--2018-05-16 --创建一个名字为V_MyClass的视图。 CREATE VIEW V_MyClass AS SELECT StuNo,StuName,ClassName FROM Student,Class WHERE Student.ClassNo=Class.ClassNo GO --对视图可以像使用表一样操作。 --查看视图内容。 SELECT * FROM V_MyClass GO --查看视图的定义。 SP_HELPTEXT V_MyClass GO --修改视图,加密视图的定义。 ALTER VIEW V_MyClass WITH ENCRYPTION AS SELECT StuNo,StuName,ClassName FROM Student,Class WHERE Student.ClassNo=Class.ClassNo GO --查看视图的定义。 SP_HELPTEXT V_MyClass GO --显示"对象'V_MyClass'的文本已加密。" --重命名视图。 SP_RENAME 'V_MyCLass','V1_MyClass' GO --删除视图。 DROP VIEW V_MyClass GO SP_HELP GO --[问题10.1]修改试图列标题 --[问题10.6]注意视图SELECT语句必须有列名。 /* 综合练习:Teacher 是00多媒体班班主任,使该老师可以查看自己班级学生选课情况(学号,姓名,课程名,种类, 学分,上课时间,开课习部) */ --步骤1:创建一个视图,显示'00多媒体'班同学的选课情况(学号,姓名,课程名,种类,学分,上课时间,开课系部) CREATE VIEW V_TeacherLi AS SELECT Student,StuNo,StuName,CouName,Kind,Credit,ScoolTime,DepartName FROM Student,Course,StuCou,Class,Department WHERE Student.StuNo=StuCou.StuNo AND Course.CouNo=StuCou.CouNo AND Student.ClassNo=Class.Class.ClassNo AND Department.DepartNo=Course.DepartNo AND ClassName GO --步骤2;在SQL Server为TeacherLi创建一个登录,登录名为:TeacherLi,登录密码为:TeacherLi USE master GO CREATE LOGIN TeacherLi WITH PASSWORD='TeacherLi' GO --测试:使用TeacherLi登录SQL Server,看是否可以登录成功? --可以登录成功。看不到Xk数据库数据。 --步骤3; USE Xk GO CREATE USER TeacherLi GO --测试:使用TeacherLi登录SQL Server,看是否可以登录成功? --可以点Xk,但是看不到用户表 --步骤4:授予TeacherLi可以看到视图V_TeacherLi USE Xk GO GRANT SELECT ON V_TeacherLi TO TeacherLi GO GRANT SELECT ON STUDENT TO TeacherLi GO 鏒t 扚 ? ? 侘絿禖睱0! 17240671.10.5实训.sql [?灜? sql 皭?--2018.4.18 USE master GO --创建数据库Sale CREATE DATABASE sale ON PRIMARY (NAME=sale, FILENAME='C:\\sale.mdf', SIZE=4MB, MAXSIZE=20MB, FILEGROWTH=1MB ) LOG ON (NAME=sale_log, FILENAME='C:\\sale_log.ldf', SIZE=10MB, MAXSIZE=20MB, FILEGROWTH=1MB) GO --向数据库增加文件组UserGroup ALTER DATABASE sale ADD FILEGROUP UserGroup GO ALTER DATABASE sale ADD FILE (NAME='sale_data3', FILENAME='D:\\sale_data3.ndf', SIZE=5MB, MAXSIZE=10MB, FILEGROWTH=1MB ) TO FILEGROUP UserGroup GO sp_help sale GO USE master GO --创建客户表结构Customer CREATE TABLE Customer (CusNO nvarchar(3) NOT NULL, CusName nvarchar(10), Address nvarchar(20)NOT NULL, Tel nvarchar(20) NOT NULL) GO --创建场品表结构Product CREATE TABLE Product (ProNO nvarchar(5) NOT NULL, ProName nvarchar(20)NOT NULL, Price Decimal(8,2) NOT NULL, Stocks Decimal(6,0) NOT NULL) GO --创建入库表结构Proln CREATE TABLE Proln (InputDate DateTime NOT NULL, ProNo nvarchar(5) NOT NULL, Quantity Decimal(6,0) NOT NULL) GO --创建销售表结构Proout CREATE TABLE Proout (SaleDate DateTime NOT NULL, CusNo nvarchar(3) NOT NULL, ProNo nvarchar(5) NOT NULL, Quantity Decimal(6,0) NOT NULL, Amount Decimal(8,2)NOT NULL) GO --向已创建的表添加数据 INSERT Customer VALUES('001','刘星','深圳','0755-22221111') INSERT Customer VALUES('002','陈笃','深圳','0755-22223333') INSERT Customer VALUES('003','李耳','深圳','0755-22225555') INSERT Customer VALUES('004','苏岩','广州','0755-22225555') INSERT Customer VALUES('005','赵颖','广州','0755-22225555') Go INSERT Customer VALUES('0001','电视','3000.00','800') INSERT Customer VALUES('0002','空调','2000.00','500') INSERT Customer VALUES('0003','床','1000.00','300') INSERT Customer VALUES('0004','餐桌','1500.00','200') INSERT Customer VALUES('0005','音响','5000.00','600') INSERT Customer VALUES('0006','沙发','6000.00','100') Go INSERT Proln VALUES('2006-1-1','00001','10') INSERT Proln VALUES('2006-1-2','00002','5') INSERT Proln VALUES('2006-1-3','00001','5') INSERT Proln VALUES('2006-2-1','00003','10') INSERT Proln VALUES('2006-2-2','00001','10') INSERT Proln VALUES('2006-2-3','00003','20') INSERT Proln VALUES('2006-3-2','00001','10') INSERT Proln VALUES('2006-3-2','00004','30') INSERT Proln VALUES('2006-3-3','00003','20') Go INSERT ProOut VALUES('2006-1-1','001','00001','10','5000') INSERT ProOut VALUES('2006-1-2','001','00002','5','4000') INSERT ProOut VALUES('2006-1-3','002','00001','5','7000') INSERT ProOut VALUES('2006-2-1','002','00003','10','6000') INSERT ProOut VALUES('2006-2-2','001','00001','10','4000') INSERT ProOut VALUES('2006-2-3','001','00003','20''6000') INSERT ProOut VALUES('2006-3-2','003','00001','10','5500') INSERT ProOut VALUES('2006-3-2','003','00004','30') INSERT ProOut VALUES('2006-3-3','002','00003','20') Go --使用ALTER TABLE 语句为已经创建的表添加主键约束、外键约束 ALTER TABLE Customer ADD CONSTRAINT PK_Customer PRIMARY KEY(CusNo) GO ALTER TABLE Product ADD CONSTRAINT PK_Product PRIMARY KEY(ProNo) GO ALTER TABLE Proln ADD CONSTRAINT PK_Proln PRIMARY KEY(ProNo) GO ALTER TABLE ProOut ADD CONSTRAINT PK_ProOut PRIMARY KEY(CusNO,ProNo) GO --约束客户表Customer的CosNo的列值长度为3,产品表Product 的ProNo 列值长度为5 ALTER TABLE Coustomer ADD CONSTRAINT CK_CusNo CHECK (CusNo like '[0-9][0-9][0-9]') GO ALTER TABLE Product ADD CONSTRAINT CK_ProNo CHECK(ProNo like'[0-9][0-9][0-9][0-9][0-9]') GO --对产品表Product 的Stocks列、Price列、入库表Proln的Quanity列、销售表ProOut 的Quanity --列值进行约束,使其值大于0 ALTER TABLE Product ADD CONSTRAINT CK_Stock CHECK(Stock>0) ALTER TABLE Product ADD CONSTRAINT CK_Price CHECK(Price>0) ALTER TABLE Proln ADD CONSTRAINT CK_Quantity CHECK (Quantity>0) ALTER TABLE ProOut ADD CONSTRAINT CK_Quantity CHECK(Quantity>0) GO --对销售表ProOut的SaleDate 列进行约束,当不输入值时,系统默认其值为系统当前日期 ALTER TABLE ProOut ADD CONSTRAINT DF_ProOut_SaleDate DEFAULT('当前日期')FOR Date GO --用户按照CusName查询客户信息,希望提高查询速度 CREATE UNIQUE INDEX IX_CusName ON Customer(CusName) GO --用户按照ProName查询产品信息,希望提高查询速度 CREATE UNIQUE INDEX IX_ProName ON Product(ProName) GO --用户按照SaleDate查询产品信息,希望提高查询速度 CREATE UNIQUE INDEX IX_SaleDate ON ProOut(SaleDate) GO --计算有多少种产品(假设为x),然后显示一条信息:共有X种产品 DECLARE @X int SET @X =(SELECT COUNT (*) FROM Product ) PRINT '共有'+convert (char(2),@x)+'种产品。' GO --编写计算n!(n=20)的程序,并显示结果。 DECLARE @X int,@product int SELECT @X=1,@product=1 WHILE @X<=20 BEGIN SELECT @X=@X+1 SELECT @product=@product*@X END SELECT '1*2*3*......*20的积'=@product GO --创建视图V_Sale1,并显示销售日期、客户编号、客户姓名、产品编号、产品名称、单价 --销售数量、销售金额 CREATE VIEW V_Sale1 AS SELECT SaleDate,Customer.CusNO,CusName,Product.ProNO,ProName,Price,Proout.Quantity, COUNT (*)Amount FROM Customer ,Product,Proln,Proout WHERE Customer.CusNO=Proout.CusNo AND Product.ProNO=Proln.ProNo AND Product.ProNO=Proout.ProNo AND Proout.Quantity=Proln.Quantity GO --创建视图V-Sale2,统计每种产品的销售数量和销售金额。统计结果包括产品编号、 --产品名称、单价、销售数量和销售金额 CREATE VIEW V_Sale2 AS SELECT Product.ProNO ,ProName,Price,Proout.Quantity ,COUNT(*)AMOUNT FROM Product ,Proout ,Proln GROUP BY ProName GO --创建视图V_Sale3,统计销售金额在10万以下的产品信息。 CREATE VIEW V_Sale3 AS SELECT Product.ProNO ,Product.ProName FROM Product ,Proout WHERE Product.ProNO=Proout.ProNo GROUP BY Product.ProNO,ProName HAVING SUM (Price*Quantity)<100000 GO &鉻 ? 鎼?跴睱0 17240671.10.6.sql 鹦?--2018-5-18 第11周周五 --存储过程 --[问题11.1],[问题11.2] USE Xk GO CREATE PROCEDURE P_Student AS SELECT * FROM Student WHERE ClassNo='20000001' GO --执行存储过程 P_Student GO --查看存储过程 SP_HELP P_Student GO SP_HELPTEXT P_Student GO SP_DEPENDS P_Student GO CREATE PROCEDURE P_StudentPara @ClassNo nvarchar(8) AS SELECT * FROM Student WHERE ClassNo=@ClassNo GO EXEC P_StudentPara '20000001' GO --[问题11.4] --问题:带参数的存储过程时传递参数有几种方式? --如何创建和执行带输出参数的存储过程?[问题11.7] EXEC P_StudentPara @ClassNo='20000001' GO EXEC P_StudentPara @ClassNo='20000002' GO CREATE PROCEDURE P_ClassNum @ClassNo nvarchar (8),@ClassNum smallint OUTPUT AS SET @ClassNum= ( SELECT COUNT(*)FROM Student WHERE ClassNo=@ClassNo=@ClassNo ) PRINT @ClassNum GO DECLARE @ClassNo nvarchar (8),@ClassNum smallint SET @ClassNo='20000001' EXEC P_ClassNum @ClassNo,@ClassNum OUTPUT SELECT @ClassNum GO ALTER PROCEDURE P_StudentPara @ClassName nvarchar(20) WITH ENCRYPTION AS SELECT ClassName,StuNo,StuName,Pwd FROM Student,Class WHERE Student.ClassNo=Class.ClassNo AND ClassName LIKE '%'+@ClassName+'%' GO USE master GO XP_LOGINCONFIG GO XP_CMDSHELL 'DIR D:\*.*' GO 挌t ? ? ? RE粣甈筁0 17240671.12.1.sql 養--2018年5月25日 --12.1创建触发器Update_Student_Trigger,实现每当修改Student表的数据时,在客户端显示"已修改Student表的数据。"的消息。 USE Xk GO CREATE TRIGGER Update_Student_Trigger ON Student FOR UPDATE AS PRINT'已修改Student表的数据。' GO UPDATE Student SET Pwd='11111111' WHERE StuNo='00000001' --12.2修改触发器Update_Student_Trigger,在确实修改了Student表的数据后返回"已修改Student表的数据。",否则返回"不存在要修改的数据。"。 USE Xk GO ALTER TRIGGER Update_Student_Trigger ON Student FOR UPDATE AS IF(SELECT COUNT(*) FROM inserted)<>0 PRINT'已修改 Student 表的数据。' ELSE PRINT '不存在要修改的数据。' GO --12.4创建替代触发器UPDATE_Department_Trigger,修改Department表的数据时触发器发器,用执行触发器的语句替代触发的SQL语句。 USE Xk GO CREATE TRIGGER UPDATE_Department_Trigger ON Department INSTEAD OF UPDATE AS PRINT'实际上并没有修改Department表的数据。' GO UPDATE Department SET DepartName='软件工程系'WHERE DepartNo='01' --12.5创建一个触发器,当插入,更新或删除StuCou表的选课数据行时,能同时更新Course表相应的报名人数。 USE Xk GO CREATE TRIGGER SetWillNum ON StuCou FOR INSERT,UPDATE,DELETE AS UPDATE Course SET WillNum=WillNum+1 WHERE CouNo=(SELECT CouNo FROM INSERTED) UPDATE Course SET WillNum=WillNum-1 WHERE CouNo=(SELECT CouNo FROM DELETED) PRINT '已自动更新Course 表相应课程的报名人数。' GO SELECT * FROM Course WHERE CouNo='002' SELECT * FROM Course WHERE CouNo='003'|鵷 ? 魸儕擯綥0 17240671.13.1.sql 鹭贒--2018-05-30 USE Xk GO SELECT * FROM Student WHERE StuName LIKE '张%' GO --创建一个游标,逐渐显示姓张同学的信息 --步骤1:声明游标 DECLARE CUR_StuName CURSOR FOR SELECT * FROM Student WHERE StuName LIKE '张%' GO --打开游标 OPEN CUR_StuName --显示游标位置的数据行 FETCH CUR_StuName WHILE @@FETCH_STATUS=0 FETCH CUR_StuName GO SELECT @@FETCH_STATUS --关闭游标 CLOSE CUR_StuName --释放游标 DEALLOCATE CUR_StuName GO --任意给出学号,然后允许修改名字。使用游标完成。 CREATE PROCEDURE P_StuName @StuNo nvarchar(8),@StuName nvarchar(10) AS --用来接收FETCH的数据行 DECLARE @StuNo nvarchar(8),@StuName nvarchar(10),@ClassNo nvarchar(8),@Pwd nvarchar(8) --声明游标 DECLARE CUR_StuName CURSOR FOR SELECT * FROM Student --打开游标 OPEN CUR_StuName --FETCH游标位置的数据到4个变量里 FETCH CUR_StuName INTO @StuNo,@StuName,@ClassN0,@Pwd WHILE @@FETCH_STATUS=0 BEGIN IF(@StuNo=@InputStuNo) UPDATE Student SET StuName=@InputStuName WHERE CURRENT OF CUR_StuName FETCH CUR_StuName INTO @StuNo,@StuName,@ClassNo,@Pwd END --关闭游标 CLOSE CUR_StuName --释放游标 DEALLOCATE CUR_StuName GO --执行,将'00000046' '张峰'名字改为'张锋' P_StuName '00000046','张锋' GO g豻 ? ` ` )锋?P芁0 17240671.14.1.sql 版蕂--2018-06-06 USE Xk GO --开始事务,一个学生报3门课 BEGIN TRANSACTION INSERT StuCou(StuNo,CouNo,WillOrder,State) VALUES ('00000025','001',1) INSERT StuCou(StuNo,CouNo,WillOrder,State) VALUES ('00000025','002',2) INSERT StuCou(StuNo,CouNo,WillOrder,State) VALUES ('00000025','003',3) --提交事务,保存在StuCou表 COMMIT TRANSACTION SELECT * FROM StuCou WHERE StuNo='00000025' GO BEGIN TRANSACTION INSERT StuCou(StuNo,CouNo,WillOrder,State) VALUES ('00000025','001',1,'报名') INSERT StuCou(StuNo,CouNo,WillOrder,State) VALUES ('00000025','002',2,'报名') INSERT StuCou(StuNo,CouNo,WillOrder,State) VALUES ('00000025','003',3,'报名') --撤销事务,撤销刚插入的3行数据 ROLLBACK TRANSACTION SELECT * FROM StuCou WHERE StuNo='00000025' GO USE Xk GO BEGIN TRANSACTION --报3门课程 INSERT StuCou(StuNo,CouNo,WillOrder) VALUES ('00000025','001',1) INSERT StuCou(StuNo,CouNo,WillOrder) VALUES ('00000025','002',2) INSERT StuCou(StuNo,CouNo,WillOrder) VALUES ('00000025','003',3) DECLARE @CountNum INT SET @CountNum=(SELECT COUNT(*)FROM StuCou WHERE StuNo='00000025') IF @CountNum>3 BEGIN ROLLBACK TRANSACTION PRINT '报名的课程超过所规定的3门,所以报名无效。' END ELSE BEGIN COMMIT TRANSACTION PRINT '恭喜,选修课程报名成功!' END --测试 SELECT *FROM StuCou WHERE StuNo='00000025' --删除 DELETE FROM StuCou WHERE StuNo='00000025'?t ? ? ? ??諴萀0 17240671.14.2.sql ?螶USE Xk GO EXEC sp_lock GO USE Xk SET DEADLOCK_PRIORITY LOW BEGIN TRANSACTION --事务,系统自动为Student表StuNo='0000001'的数据行加锁 UPDATE Student SET Pwd='1111111' WHERE StuNo='00000001' GO USE Xk GO --事务,系统自动为Course表CouNo='002'的数据行加锁 UPDATE Course SET Credit=4 WHERE CouNo='002' GO SET LOCK_TIMEOUT 1800 /*将锁超时时限设置为1800毫秒*/ GO SELECT @@LOCK_TIMEOUT GO USE master GO ?t ? ?I吢P橪0 17240671.8-1.sql 痧u--2018年-04月-25日 --检查约束: USE Xk GO ALTER TABLE Student ADD CONSTRAINT CK_StuNo CHECK (StuNo like'[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' AND StuNo<>'00000000') GO --问题[7.14] USE Xk GO ALTER TABLE Student DROP CONSTRAINT CK_StuNo GO ALTER TABLE StuCou ADD CONSTRAINT CK_WillOrder CHECK (WillOrder IN(1,2,3,4,5)) GO USE Xk GO ALTER TABLE StuCou ADD CONSTRAINT DF_StuCou_State GO USE Xk GO --创建名为UnsureDefault的默认值 CREATE DEFAULT UnsureDefault AS'待定' GO --将默认值UnsureDefault 绑定到 Course表的 Teacher列上 EXEC sp_bindefault,'Course.Teacher' GO --创建book表 USE Xk GO CREATE TABLE book ( bookID int IDENTITY(1,1), bookName varchar(30) NOT NULL ) GO --输入行数据,只输入BookName列值,标识列bookID由系统自动生成 INSERT book(bookName) VALUES('计算机网络技术') INSERT book(BookName) VALUES('软件测试技术') INSERT book(BookName) VALUES('动态WEB技术') GO --显示book表信息 SELECT * FROM book GO 暐t ? 6 6 洰澥P汱0 17240671.8.2.sql 安淣USE Xk GO CREATE UNIQUE INDEX IX_CouName ON Course (CouName) GO --2,将Student表的IX_StuName引重命名为IX_StuNameNew USE Xk GO EXEC sp_rename 'Student.IX_StuName','IX StuNameNew' GO --3,删除Course表上名字为IX_CouName的索引。 USE Xk GO DROP INDEX Course.IX_CouName GO --4,在Xk数据的Student表上查询姓“林”学生的信息,并分析哪些索引被系统采用。 USE Xk GO SET SHOWPLAN_ALL ON; GO SELECT StuNo,StuName FROM Student WHERE StuName LIKE '林%' GO SET SHOWPLAN_ALL OFF; GO --5,在Xk数据库的Student表上查询学号为“00000001”的学生信息,并分析哪些索引被系统采用。 USE Xk GO SET SHOWPLAN_ALL ON; GO SELECT StuNo FROM Student WHERE StuNo='00000001' GO SET SHOWPLAN_ALL OFF; GO --6,在Xk数据库的Student表上查询姓名为“林斌”的学生信息,并分析执行该数据查询所花费的磁盘活动量信息。 USE Xk GO SET STATISICS IO ON GO SELECT * FROM Student WHERE StuName='林斌' GO SET STATISICS IO OFF GO --7,使用UPDATE STATISTICS语句更新Xk数据库的Student表的PK_Student索引的统计信息。 USE Xk GO UPDATE STATISTICS Student PK_Student GO ?{ @ 课后实训

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

树贤森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值