我创建了两个DEFAULT
,如下所示:
CREATE DEFAULT defaultSystemStartYearMonth AS '199501'
GO
CREATE DEFAULT defaultSystemEndYearMonth AS '205012'
GO
然后尝试在RULE
中使用它们,如下所示:
CREATE RULE ruleYEARMONTH
AS
@YearMonth BETWEEN dbo.defaultSystemStartYearMonth AND dbo.defaultSystemEndYearMonth
AND (@YearMonth % 100) BETWEEN '1' AND '12'
GO
但是这个错误就失败了:
Msg 128, Level 15, State 1, Procedure ruleYEARMONTH, Line 3
The name "dbo.defaultSystemStartYearMonth" is not permitted in this context. Valid expressions are constants, constant expressions, and (in some contexts) variables. Column names are not permitted.
我想在定义DEFAULT
时使用RULE
来创建一些用户定义的数据类型,这样DEFAULT
值中的任何更改都不需要对所有{{1}进行任何更改s'或RULE
s'定义。
我该怎么做?
答案 0 :(得分:0)
不推荐使用规则:http://msdn.microsoft.com/en-us/library/ms188064.aspx
相反,你应该使用约束:
Alter table dbo.MyTable
Add constraint CK_MyTable_VerifyYearMonth
Check ( YearMonth Between 199501 And 200512 And YearMonth % 100 Between 1 and 12 )
答案 1 :(得分:0)
我没有使用DEFAULT
和RULE
,而是创建了一个新表并将默认值存储在该表中。
CREATE TABLE dbo.SystemDefaults
(
SystemStart INT NULL,
SystemEnd INT NULL
)
GO
然后创建三个标量值函数,如下所示:
- 一个用于检查年 - 月值的有效性。此函数将用于CHECK CONSTRAINT
定义。
CREATE FUNCTION fn_ValidYearMonth(@YearMonth INT)
RETURNS BIT
AS
BEGIN
-- Declare the return variable here
DECLARE @ValidYearMonth AS BIT = 0
-- Set the return variable to 1
-- if the specified year-month is in between system start and end months
-- and the month value is between 1 and 12
SELECT @ValidYearMonth = 1
FROM SystemDefaults
WHERE @YearMonth BETWEEN SystemStart AND SystemEnd
AND @YearMonth % 100 BETWEEN 1 AND 12
-- Return the result of the function
RETURN @ValidYearMonth
END
GO
- 两个返回默认的Year-Month值。这些函数将在DEFAULT CONSTRAINT
定义中使用。
CREATE FUNCTION [dbo].[fn_SystemStart]()
RETURNS INT
AS
BEGIN
-- Declare the return variable here
DECLARE @SystemStart INT = '199501'
-- Get the system start and store it in the return variable
SELECT @SystemStart = SystemStart FROM SystemDefaults
-- Return the result of the function
RETURN @SystemStart
END
GO
CREATE FUNCTION [dbo].[fn_SystemEnd]()
RETURNS INT
AS
BEGIN
-- Declare the return variable here
DECLARE @SystemEnd INT = '205012'
-- Get the system end and store it in the return variable
SELECT @SystemEnd = SystemEnd FROM SystemDefaults
-- Return the result of the function
RETURN @SystemEnd
END
GO
然后,约束定义如下:
ALTER TABLE [dbo].[Account] WITH CHECK ADD CONSTRAINT [CK_Account_ValidYearMonths] CHECK (([dbo].[fn_ValidYearMonth]([EffectiveFrom])=(1) AND [dbo].[fn_ValidYearMonth]([EffectiveTo])=(1)))
GO
ALTER TABLE [dbo].[Account] ADD CONSTRAINT [DF_Account_EffectiveFrom] DEFAULT ([dbo].[fn_SystemStart]()) FOR [EffectiveFrom]
GO
ALTER TABLE [dbo].[Account] ADD CONSTRAINT [DF_Account_EffectiveTo] DEFAULT ([dbo].[fn_SystemEnd]()) FOR [EffectiveTo]
GO
现在,在我尝试对UDF
进行一些更改之前,事情看起来还不错。我没有改变这些函数引发错误,有些消息就像这个函数被引用到其他地方一样。因此,我必须再创建两个存储过程来删除并重新创建引用这些函数的所有约束。
CREATE PROCEDURE [dbo].[sp_DBWorks_DropAndCreateCheckConstraints] --'fn_ValidYearMonth'
@FunctionName AS VARCHAR(500)
AS
BEGIN
SELECT
-- Drop SQL
'ALTER TABLE [' + S.name + '].[' + T.name + '] DROP CONSTRAINT ' + CN.name + ';',
-- Create SQL
'ALTER TABLE [' + S.name + '].[' + T.name + '] WITH CHECK ADD CONSTRAINT [' + CN.name + '] CHECK (' + CN.definition + ');'
FROM sys.check_constraints AS CN
INNER JOIN sys.tables AS T
ON CN.parent_object_id = T.object_id
INNER JOIN sys.schemas AS S
ON T.schema_id = S.schema_id
WHERE CN.definition LIKE ( '%' + @FunctionName + '%' )
END
GO
CREATE PROCEDURE [dbo].[sp_DBWorks_DropAndCreateDefaultConstraints] --'fn_SystemStart'
@FunctionName AS VARCHAR(500)
AS
BEGIN
SELECT
-- Drop SQL
'ALTER TABLE [' + S.name + '].[' + T.name + '] DROP CONSTRAINT [' + CN.name + '];',
-- Create SQL
'ALTER TABLE [' + S.name + '].[' + T.name + '] ADD CONSTRAINT [' + CN.name + '] DEFAULT ' + CN.definition + ' FOR [' + CL.name + '];'
FROM sys.default_constraints AS CN
INNER JOIN sys.columns AS CL
ON CN.parent_object_id = CL.object_id
AND CN.parent_column_id = CL.column_id
INNER JOIN sys.tables AS T
ON T.object_id = CL.object_id
INNER JOIN sys.schemas AS S
ON T.schema_id = S.schema_id
WHERE CN.definition LIKE ( '%' + @FunctionName + '%' )
END
这些过程将生成SQL
命令文本到DROP
和CREATE
这些约束。
如果要更改这些UDF
中的任何一个,那么我必须遵循以下步骤:
1.生成SQL
命令文本到DROP
和CREATE
引用该函数的约束。
2.将命令文本复制到某个文件中,以便在步骤3和5中使用。
3.放弃约束。
4.在UDF
中进行必要的更改。
5.创建在步骤3中删除的约束。
到目前为止,这是我在这种情况下的结果。任何改进此解决方案的建议都非常受欢迎。