可能在RULE定义中使用DEFAULT对象?

时间:2014-06-22 09:02:54

标签: sql sql-server sql-server-2008

我创建了两个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'定义。

我该怎么做?

2 个答案:

答案 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)

我没有使用DEFAULTRULE,而是创建了一个新表并将默认值存储在该表中。

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命令文本到DROPCREATE这些约束。


如果要更改这些UDF中的任何一个,那么我必须遵循以下步骤:
1.生成SQL命令文本到DROPCREATE引用该函数的约束。
2.将命令文本复制到某个文件中,以便在步骤3和5中使用。
3.放弃约束。
4.在UDF中进行必要的更改。
5.创建在步骤3中删除的约束。


到目前为止,这是我在这种情况下的结果。任何改进此解决方案的建议都非常受欢迎。