在CREATE TABLE语句中使用用户定义的函数

时间:2020-06-23 03:24:42

标签: sql sql-server tsql ssms

我正在尝试创建下表

CREATE TABLE Ingredient.Ingredient 
(
    GUID UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL,
    Name NVARCHAR(MAX) NOT NULL UNIQUE
)

但是我已经意识到NVARCHAR UNIQUE列的最大大小是450(至少在当前版本的SQL Server中)。为了不使用魔术文字,我创建了一个用户定义的函数,该函数返回NVARCHAR UNIQUE列的当前最大大小。

CREATE FUNCTION [Max NVARCHAR Index Size]()
RETURNS INTEGER
BEGIN
    RETURN(450)
END

此函数调用为时正确运行

SELECT dbo.[Max NVARCHAR Index Size]()

我希望在CREATE TABLE语句中使用此功能,但如下所示出错。

CREATE TABLE Ingredient.Ingredient 
(
    GUID UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL,
    Name NVARCHAR(dbo.[Max NVARCHAR Index Size]()) NOT NULL UNIQUE
)

错误:

第15层状态1线13的消息102
'('

附近的语法不正确

为避免这种情况,我使用函数的值创建了一个变量,然后使用该变量,但这也不起作用。

DECLARE
    @NVARCHARIndexSize INTEGER = dbo.[MAX NVARCHAR Index Size]()

CREATE TABLE Ingredient.Ingredient 
(
    GUID UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL,
    Name NVARCHAR(@NVARCHARIndexSize) NOT NULL UNIQUE
)

错误:

第15层状态1线13的消息102
'@NVARCHARIndexSize'附近的语法不正确

第13行是Name NVARCHAR(@NVARCHARIndexSize) NOT NULL UNIQUE

CREATE TABLE语句中是否可以使用变量/函数代替文字?

谢谢。

3 个答案:

答案 0 :(得分:3)

您可以使用以下语法在SQL Server中创建自定义类型

CREATE TYPE MyCustomType  
FROM NVARCHAR(420); 

以后可以在创建表时使用自定义类型

CREATE TABLE Ingredient 
(
    GUID UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL,
    [Name] MyCustomType NOT NULL UNIQUE
)

答案 1 :(得分:2)

DDL无法参数化。您必须为此使用动态SQL。例如

val (p1, p2, p3) = when (enum: SomeEnum) {
    SomeEnum.x -> listOf<String>("NameX", "100", "true")
    SomeEnum.y -> listOf<String>("NameY", "200", "false")
}

答案 2 :(得分:1)

在SQL Server 2016之前,最大密钥长度为900字节。 MSDN Reference

索引键大小

对于聚集索引,索引键的最大大小为900字节,对于非聚集索引,索引键的最大大小为1700字节。 (之前 SQL数据库和SQL Server 2016(13.x)的限制始终为900 个字节。)超过字节数限制的varchar列上的索引可以是 如果列中的现有数据不超过以下限制,则创建 创建索引的时间;但是,随后的插入或更新 对列的操作导致总大小大于 限制将失败。聚集索引的索引键不能包含 ROW_OVERFLOW_DATA中具有现有数据的varchar列 分配单位。如果在varchar列上创建了聚集索引 现有数据位于IN_ROW_DATA分配单元中, 对列的后续插入或更新操作将推动 行外数据将失败。

非聚集索引可以在以下级别的叶级别中包含非关键列: 索引。数据库引擎不考虑这些列 计算索引键大小时

您可以定义带有检查约束的NVARCHAR(450)列,以确保您的数据不超过450个字符。我建议您使用DATALENGTH来确保列长度为<= 900。

CREATE TABLE #test(id int identity(1,1) not null, 
a NVARCHAR(500) CHECK (DATALENGTH(a) <= 900),
CONSTRAINT ak_a unique(a))


insert into #test
values('a') -- 1 row affected

insert into #test
values(REPLICATE('a',450)) -- 1 row affected

insert into #test
values(REPLICATE('a',451)) -- Error 

消息547,级别16,状态0,第12行INSERT语句冲突 且其检查约束为“ CK __#test____________a__AC6651A7”。的 数据库“ tempdb”,表“ #test”,列“ a”中发生冲突。

将来,当您升级到更高版本时,可以相应地增加NVARCHAR和CHECK约束的长度。

相关问题