在客户表中,我有电子邮件列,其中可能包含多个以(;)分隔的电子邮件。
我使用拆分功能为每个客户分隔电子邮件:
Cust1 --->email1
cust1 --->email2
cust1 ---> emailN
我可以向同一位客户添加更多电子邮件。
我希望能够更新或删除拆分的电子邮件,换句话说,如果email2 = abc@company.com
我想将其更改为xyz@company.com
或删除它。
是否可以使用分离功能?或任何其他方式?
这是我的分割功能
CREATE FUNCTION [dbo].[fnSplitString]
(
@string NVARCHAR(MAX),
@delimiter CHAR(1)
)
RETURNS @output TABLE(splitdata NVARCHAR(MAX)
)
BEGIN
DECLARE @start INT, @end INT
SELECT @start = 1, @end = CHARINDEX(@delimiter, @string)
WHILE @start < LEN(@string) + 1 BEGIN
IF @end = 0
SET @end = LEN(@string) + 1
INSERT INTO @output (splitdata)
VALUES(SUBSTRING(@string, @start, @end - @start))
SET @start = @end + 1
SET @end = CHARINDEX(@delimiter, @string, @start)
END
RETURN
END
调用该功能拆分电子邮件:
select tb1.custId, split.splitdata from customers tb1
outer apply [dbo].[fnSplitString] (tb1.email,';') split
where tb1.Email like '%;%'
向同一客户添加新电子邮件:
UPDATE Customers set Email=Email+';new Email' Where CustId='customerId'
更新或删除现有电子邮件,有什么建议吗?
提前致谢
答案 0 :(得分:2)
首先,您的分割功能不是最佳的。它正在以RBAR方式进行分割。有许多方法可以以基于集合的方式执行此操作。这是一个使用XML,取自Aaron Bertrand的article。
我更喜欢Jeff Moden的DelimitedSplit8K,但为了简单起见,我将使用XML拆分。
CREATE FUNCTION dbo.SplitStrings_XML
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
);
现在您已经拥有了基于集合的拆分器,现在是时候进行CRUD操作了:
SELECT
分割的电子邮件:
SELECT
c.CustomerId,
Email = s.Item
FROM Customer c
CROSS APPLY dbo.SplitStrings_XML(c.Emails, ';') s
ADD
新Email
到特定Customer
:
DECLARE @email NVARCHAR(100) = 'abc@company.com'
UPDATE Customer
SET Emails = Emails + ';' + @email
WHERE
CustomerId = 1
AND CHARINDEX(@email, Emails) = 0 -- Prevent duplicate Email
UPDATE
Email
Customer
DECLARE @to_update NVARCHAR(100) = 'abc@company.com',
@new_email NVARCHAR(100) = 'xyz@company.com';
;WITH Cte AS(
SELECT
c.CustomerId,
Email = CASE WHEN s.Item = @to_update THEN @new_email ELSE s.Item END
FROM Customer c
CROSS APPLY dbo.SplitStrings_XML(c.Emails, ';') s
)
UPDATE c
SET Emails = STUFF((
SELECT ';' + Email
FROM Cte
WHERE CustomerId = c.CustomerId
FOR XML PATH(''), type).value('.[1]','nvarchar(max)')
,1, 1, '')
FROM Customer c
SELECT * FROM Customer
REPLACE
UPDATE Customer
SET Emails = REPLACE(Emails, @to_update, @new_email)
WHERE CustomerId = 1
您也可以使用DELETE
:
Email
从列表中DECLARE @to_delete NVARCHAR(100) = 'abc@company.com';
;WITH Cte AS(
SELECT
c.CustomerId,
Email = s.Item
FROM Customer c
CROSS APPLY dbo.SplitStrings_XML(c.Emails, ';') s
WHERE s.Item <> @to_delete
)
UPDATE c
SET Emails = STUFF((
SELECT ';' + Email
FROM Cte
WHERE CustomerId = c.CustomerId
FOR XML PATH(''), type).value('.[1]','nvarchar(max)')
,1, 1, '')
FROM Customer c
SELECT * FROM Customer
到REPLACE
:
DECLARE @to_delete NVARCHAR(100) = 'abc@company.com';
UPDATE Customer
SET Emails = REPLACE(Emails, @to_delete + ';', '')
WHERE CustomerId = 1
您也可以使用$userAmt
:
$points
现在,我将把它留作练习,将它们转换为存储过程。 :)