我花了很多时间调查这是否可以在数据库之外完成,但老实说我不这么认为,也不是很容易。我们使用VBA通过Access 2010访问表中的数据,所以我想我可以做到 通过前端软件中的操作。容易完成但是我无法控制两种排列。
我有一个包含多列的表[TableData]。我们有一些外部提供的软件,一次填充表约20-30行。其中一个字段[波动]目前允许我们传输最多60个字符的数据,我们的目的是以1.1,1.2,1.3,1.4,1.5,1.6格式发送数据,其中我们有六个数字,最多两个小数以逗号分隔的地方,没有空格。列名称Fluc1,Fluc2,Flu3等。
我想要做的是在SQL数据库中创建一个触发器,该数据库在插入行后操作,只有当存在由五个逗号分隔的6个值时才将上面的内容拆分为六个新列。
然后我需要完成6个值的数学运算,但至少我会让它们完成数字以完成数学运算。
我对触发器一无所知,因此非常感谢任何帮助。
示例数据示例如下: 101.23,100.45,101.56,102.89,101,74,100.25 1.05,1.09,1.05,0.99,0.99,0.98 等
我有VBA代码来分割数据,并且事后会通过SELECT查询执行此操作,但由于我无法控制从外部软件输入的数据,因此认为触发器会更有用。
VBA代码。
'This function returns the string data sperated by commas
Public Function FluctuationSeperation(strFluctuationData As String) As Variant
Dim strTest As String
Dim strArray() As String
Dim intCount As Integer
strArray = Split(strFluctuationData, ",")
Dim arr(5) As Variant
For intCount = LBound(strArray) To UBound(strArray)
arr(intCount) = Trim(strArray(intCount))
Next
FluctuationSeperation = arr
End Function
答案 0 :(得分:1)
编写触发器时,需要注意它可以为多个插入的行启动。有inserted
内置表别名可用于此目的。您需要遍历所有插入的记录并单独更新它们。您需要使用主键(我已假设列id
)来匹配插入的记录和要更新的记录。
CREATE TRIGGER TableData_ForInsert
ON [TableData]
AFTER INSERT
AS
BEGIN
DECLARE @id int
DECLARE @Fluctuation varchar(max)
DECLARE i CURSOR FOR
SELECT id, Fluctuation FROM inserted
FETCH NEXT FROM i INTO @id, @Fluctuation
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @pos1 int = charindex(',',@Fluctuation)
DECLARE @pos2 int = charindex(',',@Fluctuation, @pos1+1)
DECLARE @pos3 int = charindex(',',@Fluctuation, @pos2+1)
DECLARE @pos4 int = charindex(',',@Fluctuation, @pos3+1)
UPDATE [TableData]
SET fluc1 = ltrim(substring(@Fluctuation,1,@pos1-1)),
fluc2 = ltrim(substring(@Fluctuation,@pos1+1,@pos2-@pos1-1)),
fluc3 = ltrim(substring(@Fluctuation,@pos2+1,@pos3-@pos2-1)),
fluc4 = ltrim(substring(@Fluctuation,@pos3+1,@pos4-@pos3-1)),
fluc5 = ltrim(substring(@Fluctuation,@pos4+1,999))
WHERE id = @id -- need to find TableData record to update by inserted id
FETCH NEXT FROM i INTO @id, @Fluctuation
END
END
但是因为游标在many cases considered as a bad practice中,所以最好将其写为基于集合的命令。它可以通过APPLY子句实现,如下所示:
CREATE TRIGGER TableData_ForInsert
ON [TableData]
AFTER INSERT
AS
BEGIN
UPDATE t SET
fluc1 = SUBSTRING(t.fluctuation, 0, i1.i),
fluc2 = SUBSTRING(t.fluctuation, i1.i+1, i2.i - i1.i -1),
fluc3 = SUBSTRING(t.fluctuation, i2.i+1, i3.i - i2.i -1),
fluc4 = SUBSTRING(t.fluctuation, i3.i+1, i4.i - i3.i -1),
fluc5 = SUBSTRING(t.fluctuation, i4.i+1, 999)
FROM [TableData] t
OUTER APPLY (select charindex(',', t.fluctuation) as i) i1
OUTER APPLY (select charindex(',', t.fluctuation, i1.i+1) as i) i2
OUTER APPLY (select charindex(',', t.fluctuation, i2.i+1) as i) i3
OUTER APPLY (select charindex(',', t.fluctuation, i3.i+1) as i) i4
JOIN INSERTED new ON new.ID = t.ID -- need to find TableData record to update by inserted id
END
这个代码示例缺少处理格式错误的字符串,它总是期望5个数字由4个逗号分隔。
有关如何在SQL Server中拆分字符串的更多提示,请选中this link。
测试用例:
DECLARE @test TABLE
(
id int,
Fluctuation varchar(max),
fluc1 numeric(9,3) NULL,
fluc2 numeric(9,3) NULL,
fluc3 numeric(9,3) NULL,
fluc4 numeric(9,3) NULL,
fluc5 numeric(9,3) NULL
)
INSERT INTO @test (id, Fluctuation) VALUES(1, '1.2,5,8.52,6,7.521')
INSERT INTO @test (id, Fluctuation) VALUES(2, '2.2,6,9.52,7,8.521')
INSERT INTO @test (id, Fluctuation) VALUES(3, '2.5,3,4.52,9,7.522')
INSERT INTO @test (id, Fluctuation) VALUES(4, '2.53,4.52,97.522') -- this fails
UPDATE t SET
fluc1 = CASE WHEN i1.i<0 THEN NULL ELSE SUBSTRING(t.fluctuation, 0, i1.i) END,
fluc2 = CASE WHEN i2.i<0 THEN NULL ELSE SUBSTRING(t.fluctuation, i1.i+1, i2.i - i1.i -1) END,
fluc3 = CASE WHEN i3.i<0 THEN NULL ELSE SUBSTRING(t.fluctuation, i2.i+1, i3.i - i2.i -1) END,
fluc4 = CASE WHEN i4.i<0 THEN NULL ELSE SUBSTRING(t.fluctuation, i3.i+1, i4.i - i3.i -1) END,
fluc5 = CASE WHEN i4.i<0 THEN NULL ELSE SUBSTRING(t.fluctuation, i4.i+1, 999) END
FROM @test t
OUTER APPLY (select charindex(',', t.fluctuation) as i) i1
OUTER APPLY (select charindex(',', t.fluctuation, i1.i+1) as i) i2
OUTER APPLY (select charindex(',', t.fluctuation, i2.i+1) as i) i3
OUTER APPLY (select charindex(',', t.fluctuation, i3.i+1) as i) i4
SELECT * FROM @test