SQL Server-我可以用其他东西代替那些游标吗?

时间:2019-01-20 15:00:38

标签: sql sql-server-2008 triggers

首先,这是一些要测试的表和数据:

CREATE TABLE [dbo].[MyOrders]
(
    [ID] [int] NOT NULL,
    [ref_type] [nchar](1) NOT NULL,
    [ref_num] [nvarchar](15) NULL,
    [req_cert] [nvarchar](255) NULL,
 CONSTRAINT [PK_MyOrders] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[MyJobs]
(
    [job_id] [nvarchar](15) NOT NULL,
    [job_message] [nvarchar](255) NULL,
 CONSTRAINT [PK_MyJobs] PRIMARY KEY CLUSTERED 
(
    [job_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[MyTypes]
(
    [type] [nvarchar](255) NOT NULL,
    [value] [nvarchar](255) NOT NULL
) ON [PRIMARY]
GO

INSERT INTO [dbo].[MyOrders] ([ID], [ref_type], [ref_num], [req_cert])
VALUES (1, 'J', 'Job0001', 'Cert1')
GO

INSERT INTO [dbo].[MyJobs] ([job_id], [job_message])
VALUES ('Job0001', 'Accepted')
GO

INSERT INTO [dbo].[MyTypes] ([type], [value])
VALUES ('MyCerts', 'Cert1'),
       ('MyCerts', 'Cert2')
GO

MyOrders保留了我的订单,这些订单可以引用表MyJobs中的作业。 MyOrder可以指定req_cert,然后将其显示在job_message字段中。 req_cert将具有MyTypes表中的值,其中type == 'MyCert'

我想做的是创建一个触发器,当req_cert表的ref_numMyOrders列更新时,它将执行以下操作:

  1. 这两个字段之一是否已更新?

  2. ref_type == Jref_num is not null吗?

  3. 选择现有的job_message并检查MyTypes表中是否没有值。

  4. 如果有,请用req_cert

  5. 中的值替换
  6. 如果没有,请附加req_cert

我为此编写了触发器,但是我不知道这是否是最好的方法:

ALTER TRIGGER [dbo].[UpdateCert] 
ON [dbo].[MyOrders]
FOR UPDATE
AS
    SET NOCOUNT ON

    IF (NOT UPDATE ([req_cert])
        AND NOT UPDATE ([ref_num]))
       RETURN

    DECLARE @ID NVARCHAR(50)
    DECLARE @Certificate NVARCHAR(255)
    DECLARE @OldValue NVARCHAR(255)
    DECLARE @Found TINYINT
    DECLARE @JobMessage NVARCHAR(2000)

    DECLARE InsertCursor CURSOR FAST_FORWARD FOR
        SELECT ref_num, req_cert
        FROM Inserted

    OPEN InsertCursor

    FETCH NEXT FROM InsertCursor INTO @ID, @Certificate

    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF (NOT EXISTS (SELECT ref_num
                        FROM MyOrders
                        WHERE ref_type = 'J'
                          AND ref_num = @ID))
        BEGIN
            FETCH NEXT FROM InsertCursor INTO @ID, @Certificate
            CONTINUE
        END

        SELECT @JobMessage = job_message
        FROM MyJobs
        WHERE job_id = @ID

        DECLARE CertCursor CURSOR FAST_FORWARD FOR
             SELECT [Value]
             FROM MyTypes
             WHERE [Type] = 'MyCerts'

        OPEN CertCursor

        FETCH NEXT FROM CertCursor INTO @OldValue

        WHILE @@FETCH_STATUS = 0
        BEGIN
            IF (@JobMessage LIKE '%' + @OldValue + '%')
            BEGIN
                SET @Found = 1
                BREAK
            END

            FETCH NEXT FROM CertCursor INTO @OldValue
        END

        CLOSE CertCursor
        DEALLOCATE CertCursor

        IF (@Found = 1)
        BEGIN
            SELECT @JobMessage = REPLACE(@JobMessage, @OldValue, '')
        END

        UPDATE MyJobs WITH (ROWLOCK)
        SET job_message = ISNULL(@Certificate, '') + ISNULL(@JobMessage, '')
        WHERE MyJobs.job_id = @ID

        FETCH NEXT FROM InsertCursor INTO @ID, @Certificate
    END

    CLOSE InsertCursor
    DEALLOCATE InsertCursor

EXPECETD RESULTS(假设上面的数据):

UPDATE MyOrders
SET req_cert = 'Cert1'
WHERE ID = 1

job_message应该是Cert1 Accepted

UPDATE MyOrders
    SET req_cert = 'Cert2'
    WHERE ID = 1

job message应该是Cert2 Accepted

UPDATE MyOrders
SET ref_num = null
WHERE ID = 1
GO
UPDATE MyOrders
SET  req_cert = 'Cert1'
WHERE ID = 1
GO
UPDATE MyOrders
SET ref_num = 'Job0001'
WHERE ID = 1

job message应该是Cert1 Accepted

0 个答案:

没有答案