我必须在SQL Server触发器中创建一个函数,用于在插入后生成随机数。我想用生成的随机数更新列,请帮助我在代码中遗漏的内容。
如果您了解其他方式,请提出完成任务的方法。
这是我的SQL Server触发器:
ALTER TRIGGER [dbo].[trgEnquiryMaster]
ON [dbo].[enquiry_master]
AFTER INSERT
AS
declare @EnquiryId int;
declare @ReferenceNo varchar(50);
declare @GenReferenceNo NVARCHAR(MAX);
select @EnquiryId = i.enquiry_id from inserted i;
select @ReferenceNo = i.reference_no from inserted i;
BEGIN
SET @GenReferenceNo = 'CREATE FUNCTION functionRandom (@Reference VARCHAR(MAX) )
RETURNS VARCHAR(MAX)
As
Begin
DECLARE @r varchar(8);
SELECT @r = coalesce(@r, '') + n
FROM (SELECT top 8
CHAR(number) n FROM
master..spt_values
WHERE type = P AND
(number between ascii(0) and ascii(9)
or number between ascii(A) and ascii(Z)
or number between ascii(a) and ascii(z))
ORDER BY newid()) a
RETURNS @r
END
'
EXEC(@GenReferenceNo)
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
-- update statements for trigger here
UPDATE enquiry_master
SET reference_no ='updated'
WHERE enquiry_id = @EnquiryId
END
答案 0 :(得分:3)
触发器应该灵活且快速 - 它不能进行繁重且耗时的处理,并且绝对没有地方可以创建新的数据库对象,因为(a)触发器在引发它的代码的上下文,以及(b)你无法控制触发器被触发的时间和频率。
你需要
定义并创建您的函数,以便在数据库设置期间生成随机值 - 一次,在对数据库执行任何操作之前
重写您的触发器以考虑可以一次插入多行,在这种情况下,Inserted
表将包含多行,这些行都必须是处理。
所以你的触发器看起来像这样(我有几个假设 - 例如enquiry_id
是你桌子上的主键 - 你需要这个来建立数据表和你之间的INNER JOIN
Inserted
伪表:
ALTER TRIGGER [dbo].[trgEnquiryMaster]
ON [dbo].[enquiry_master]
AFTER INSERT
AS
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
-- update statements for trigger here
UPDATE enq
SET reference_no = dbo.GenerateRandomValue(.....)
FROM enquiry_master enq
INNER JOIN inserted i ON enq.enquiry_id = i.enquiry_id
答案 1 :(得分:3)
要生成随机数,只需调用SQL Server 2008中引入的CRYPT_GEN_RANDOM:
SELECT CRYPT_GEN_RANDOM(5) AS [Hex],
CONVERT(VARCHAR(20), CRYPT_GEN_RANDOM(5), 2) AS [HexStringWithout0x],
CONVERT(VARCHAR(20), CRYPT_GEN_RANDOM(10)) AS [Translated-ASCII],
CONVERT(NVARCHAR(20), CRYPT_GEN_RANDOM(20)) AS [Translated-UCS2orUTF16]
返回:
Hex HexStringWithout0x Translated-ASCII Translated-UCS2orUTF16
0x4F7D9ABBC4 0ECF378A7A ¿"bü<ݱØï 붻槬㟰添䛺⯣왚꒣찭퓚
如果你只有0 - 9和A - F,那么CONVERT(VARCHAR(20), CRYPT_GEN_RANDOM(5), 2)
就是你所需要的。
有关详细信息,请参阅DBA.StackExchange上有关类似问题的答案:
该链接答案的“更新”部分中显示的UPDATE
语句是您想要的,只需删除WHERE
条件并将JOIN
添加到Inserted
即可伪表。
查询应如下所示:
DECLARE @Length INT = 10;
UPDATE em
SET em.[reference_no] = rnd.RandomValue
FROM dbo.enquiry_master em
INNER JOIN Inserted ins
ON ins.enquiry_id = em.enquiry_id
CROSS APPLY dbo.GenerateReferenceNo(CRYPT_GEN_RANDOM((em.[enquiry_id] % 1) + @Length)) rnd;
由于功能略有不同,以下是为了获得大写和小写字母的方式:
CREATE FUNCTION dbo.GenerateReferenceNo(@RandomValue VARBINARY(20))
RETURNS TABLE
WITH SCHEMABINDING
AS RETURN
WITH base(item) AS
(
SELECT NULL UNION ALL SELECT NULL UNION ALL SELECT NULL UNION ALL
SELECT NULL UNION ALL SELECT NULL UNION ALL SELECT NULL
), items(item) AS
(
SELECT NULL
FROM base b1
CROSS JOIN base b2
)
SELECT (
SELECT TOP (LEN(@RandomValue))
SUBSTRING('1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm',
(CONVERT(TINYINT, SUBSTRING(@RandomValue, 1, 1)) % 62) + 1,
1) AS [text()]
FROM items
FOR XML PATH('')
) AS [RandomReferenceNo];
GO
并且请按照上面显示的用法,传递CRYPT_GEN_RANDOM((em.[enquiry_id] % 1) + @Length)
,不:CRYPT_GEN_RANDOM(@RefferenceNOLength)
。
其他说明:
newid()
(在ORDER BY
中)不是,所以该函数无论如何都不起作用在一个函数中允许。您无需发出两个单独的SELECT
来设置两个不同的变量。您可以执行以下操作:
SELECT @EnquiryId = i.enquiry_id,
@ReferenceNo = i.reference_no
FROM TableName i;
ASCII('A')
而不是ASCII(A)
。<强>更新强>
完整的触发器定义应如下所示:
ALTER TRIGGER [dbo].[trgEnquiryMaster]
ON [dbo].[enquiry_master]
AFTER INSERT
AS
BEGIN
DECLARE @Length INT = 10;
UPDATE em
SET em.[reference_no] = rnd.RandomValue
FROM dbo.enquiry_master em
INNER JOIN Inserted ins
ON ins.enquiry_id = em.enquiry_id
CROSS APPLY dbo.GenerateReferenceNo(
CRYPT_GEN_RANDOM((em.[enquiry_id] % 1) + @Length)
) rnd;
END;