带有检查约束的用户定义表类型

oxw*_*der 2 t-sql sql-server sql-server-2017

我想创建一个用于存储过程的表类型,但我想确保传递到表中的参数之一是两个值之一。

如果我正确解释了文档,唯一可用的列约束是主键,但如果我错了,请纠正我。

这是我尝试过的:

create type dealerDisable as table
(id int not null,
dealerNo varchar(10) not null,
dealerName varchar(50),
disabling varchar(5),
constraint ratesOrAll 
check (disabling in ('Rates','All')),
dateAdded date)
Run Code Online (Sandbox Code Playgroud)

这是我得到的错误,并不是那么有启发性: 在此处输入图片说明

Aar*_*and 5

创建表类型语法有点严格——它不支持命名约束,以及与CREATE TABLE.

CREATE TYPE dbo.dealerDisable AS TABLE -- ALWAYS use schema!
(
  id int not null,
  dealerNo varchar(10) not null,
  dealerName varchar(50),
  disabling varchar(5) check (disabling in ('Rates','All')),
  dateAdded date
);
Run Code Online (Sandbox Code Playgroud)

当您尝试插入一个值时,您可以看到系统必须为表的每个实例创建一个唯一的约束名称:

DECLARE @d dbo.dealerDisable2;
INSERT @d VALUES(1,'blat','foo','None',getdate());

DECLARE @e dbo.dealerDisable2;
INSERT @e VALUES(1,'blat','foo','None',getdate());
Run Code Online (Sandbox Code Playgroud)

错误:

消息 547,级别 16,状态 0
INSERT 语句与 CHECK 约束“CK__ #BCAA5D0E__disab__BD9E8147 ”冲突。
...

消息 547,级别 16,状态 0
INSERT 语句与 CHECK 约束“CK__ #AAF87C65__disab__ABECA09E ”冲突。
...

如果你考虑一下这背后的机制,那就说得通了。对于某些类型的约束,数据库中只能有一个同名。这将产生相同类型的错误,例如:

CREATE TABLE #a(id int, CONSTRAINT PK1 PRIMARY KEY (id));

CREATE TABLE #b(id int, CONSTRAINT PK1 PRIMARY KEY (id));
Run Code Online (Sandbox Code Playgroud)

现在,虽然您可以根据需要使用尽可能多的同名检查约束,但这可能只是对语法的直接简化。

  • @Muflix 在线图书中的[语法图](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-type-transact-sql)说不。 (2认同)