将一个字符串的一部分插入到另一个字符串的给定位置
Insert a portion of one string into another string in a given position
我在 sql 服务器
中有这些列
LineNumber DocumentNumber
1.1/2-GM-100-10026-G01-N-1-1001 DW-2224-100-1330-1001
10-FW-130-13576-B90-N-1-100-1001 DW-2224-100-1330-1001
4-IA-160-12325-B10-N-1-2001 DW-2224-160-1330-2001
UG-12-CS-160-160CMH306-B93-N-1-1062 DW-2224-160-1433-1062
24-SL-160-12116-B12-H-1-160-MMP DW-2224-160-1433-1062
我想根据 documentnumber
更新 linenumber
。我只想添加 documentnumber
的第三部分,我的意思是 e.x“100,160,100 等”添加到我的line number
在最后一部分之前我的意思是 2001,1001
我期望的结果是:
LineNumber DocumentNumber
1.1/2-GM-100-10026-G01-N-1-100-1001 DW-2224-100-1330-1001
10-FW-130-13576-B90-N-1-100-1001 DW-2224-100-1330-1001
4-IA-160-12325-B10-N-1-160-2001 DW-2224-160-1330-2001
UG-12-CS-160-160CMH306-B93-N-1-160-1062 DW-2224-160-1433-1062
24-SL-160-12116-B12-H-1-160-MMP DW-2224-160-1433-1062
docnumber的第三部分添加到linenumber。但是有些linenumber有这部分,不应该添加。
我想在 sql 服务器中更新它。
\SELECT [Id]
,[LineNumber]
,[DocumentNumber]
FROM [SPMS2].[dbo].[Lines]
更新
这是@Shnugo 回答的结果。但是 - 如您所见 - 在某些情况下该部分已经存在。插入后这部分翻了一番,但我只需要一次!
抱歉,这个设计太糟糕了...如果您需要这样的字符串,它应该在您需要的时候根据一些业务规则从正确的部分中构建出来。你真的应该规范化这个!
但如果非要坚持的话,可以这样试试:
DECLARE @tbl TABLE(LineNumber VARCHAR(100),DocumentNumber VARCHAR(100));
INSERT INTO @tbl VALUES
('1.1/2-GM-100-10026-G01-N-1-1001','DW-2224-100-1330-1001')
,('10-FW-130-13576-B90-N-1-100-1001','DW-2224-100-1330-1001')
,('4-IA-160-12325-B10-N-1-2001','DW-2224-160-1330-2001')
,('UG-12-CS-160-160CMH306-B93-N-1-1062','DW-2224-160-1433-1062')
,('24-SL-160-12116-B12-H-1-160-MMP','DW-2224-160-1433-1062');
SELECT STUFF(LineNumber
,LEN(LineNumber)-CHARINDEX('-',REVERSE(LineNumber)) + 1
,0
,'-' + CAST('<x>' + REPLACE(DocumentNumber,'-','</x><x>') + '</x>' AS XML).value('/x[3]','varchar(max)'))
FROM @tbl AS tbl
这是结果
1.1/2-GM-100-10026-G01-N-1-100-1001
10-FW-130-13576-B90-N-1-100-100-1001
4-IA-160-12325-B10-N-1-160-2001
UG-12-CS-160-160CMH306-B93-N-1-160-1062
24-SL-160-12116-B12-H-1-160-160-MMP --Here the 160 is twice due to the test data...
转换为 XML 允许 select 您的 DocumentNumber 的第三部分很容易(但要注意 <, > and &
等禁用字符 ). STUFF
函数将此字符串放在正确的位置(反转字符串中的 first 连字符)
更新
根据您的评论,这个新查询将首先提取两个部分并进行比较。仅当行号中的倒数第二部分不等于 DocumentNumber
中的第三部分时才会插入
SELECT CASE WHEN SecondLastInLineNumber=ThirdInDocumentNumber THEN LineNumber
ELSE
STUFF(LineNumber
,LEN(LineNumber)-CHARINDEX('-',REVERSE(LineNumber)) + 1
,0
,'-' + ThirdInDocumentNumber)
END AS NewLineNumber
FROM @tbl AS tbl
CROSS APPLY
(
SELECT REVERSE(CAST('<x>' + REPLACE(REVERSE(LineNumber),'-','</x><x>') + '</x>' AS XML).value('/x[2]','varchar(max)'))
,CAST('<x>' + REPLACE(DocumentNumber,'-','</x><x>') + '</x>' AS XML).value('/x[3]','varchar(max)')
) AS Parts(SecondLastInLineNumber,ThirdInDocumentNumber)
结果
1.1/2-GM-100-10026-G01-N-1-100-1001
10-FW-130-13576-B90-N-1-100-1001
4-IA-160-12325-B10-N-1-160-2001
UG-12-CS-160-160CMH306-B93-N-1-160-1062
24-SL-160-12116-B12-H-1-160-MMP
但是@Shnugo 给出的解决方案是好的。
您仍然可以尝试以下选项。
创建一个按给定字符拆分数据的函数,如下所示:
CREATE FUNCTION [dbo].[fnSplit]
(
@String NVARCHAR(4000),
@Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)
FROM Split
)
现在,使用下面的 select 语句
SELECT REPLACE
(
LineNumber,
'-'+ REVERSE(Substring(REVERSE(LineNumber),0, charindex('-',REVERSE(LineNumber)))),
'-'+
(
SELECT Data FROM [dbo].[fnSplit] (DocumentNumber,'-') Where Id=3
)+'-'+ REVERSE(Substring(REVERSE(LineNumber),0, charindex('-',REVERSE(LineNumber))))
)
FROM TableName
CREATE TABLE [dbo].[Doc](
[id] [int] IDENTITY(1,1) NOT NULL,
[LineNumber] [varchar](200) NULL,
[DocumentNumber] [varchar](200) NULL
) ON [PRIMARY]
GO
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('1.1/2-GM-100-10026-G01-N-1-1001','DW-2224-100-1330-1001')
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('10-FW-130-13576-B90-N-1-100-1001','DW-2224-100-1330-1001')
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('4-IA-160-12325-B10-N-1-2001','DW-2224-160-1330-2001')
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('UG-12-CS-160-160CMH306-B93-N-1-1062','DW-2224-160-1433-1062')
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('24-SL-160-12116-B12-H-1-160-MMP','DW-2224-160-1433-1062')
GO
SELECT
Id,
DocumentNumber,
LineNumber,
REVERSE(STUFF(REVERSE(LineNumber), CHARINDEX('-', REVERSE(LineNumber)) + 1, 0, REVERSE(REVERSE(REVERSE('-' + SUBSTRING(DocumentNumber, 9, LEN(DocumentNumber) - 18))))))
AS LineNumberInRequiredFormat
FROM [Doc]
Result
LineNumberInRequiredFormat
*********************************
1.1/2-GM-100-10026-G01-N-1-100-1001
10-FW-130-13576-B90-N-1-100-100-1001
4-IA-160-12325-B10-N-1-160-2001
UG-12-CS-160-160CMH306-B93-N-1-160-1062
24-SL-160-12116-B12-H-1-160-160-MMP
我在 sql 服务器
中有这些列LineNumber DocumentNumber
1.1/2-GM-100-10026-G01-N-1-1001 DW-2224-100-1330-1001
10-FW-130-13576-B90-N-1-100-1001 DW-2224-100-1330-1001
4-IA-160-12325-B10-N-1-2001 DW-2224-160-1330-2001
UG-12-CS-160-160CMH306-B93-N-1-1062 DW-2224-160-1433-1062
24-SL-160-12116-B12-H-1-160-MMP DW-2224-160-1433-1062
我想根据 documentnumber
更新 linenumber
。我只想添加 documentnumber
的第三部分,我的意思是 e.x“100,160,100 等”添加到我的line number
在最后一部分之前我的意思是 2001,1001
我期望的结果是:
LineNumber DocumentNumber
1.1/2-GM-100-10026-G01-N-1-100-1001 DW-2224-100-1330-1001
10-FW-130-13576-B90-N-1-100-1001 DW-2224-100-1330-1001
4-IA-160-12325-B10-N-1-160-2001 DW-2224-160-1330-2001
UG-12-CS-160-160CMH306-B93-N-1-160-1062 DW-2224-160-1433-1062
24-SL-160-12116-B12-H-1-160-MMP DW-2224-160-1433-1062
docnumber的第三部分添加到linenumber。但是有些linenumber有这部分,不应该添加。
我想在 sql 服务器中更新它。
\SELECT [Id]
,[LineNumber]
,[DocumentNumber]
FROM [SPMS2].[dbo].[Lines]
更新
这是@Shnugo 回答的结果。但是 - 如您所见 - 在某些情况下该部分已经存在。插入后这部分翻了一番,但我只需要一次!
抱歉,这个设计太糟糕了...如果您需要这样的字符串,它应该在您需要的时候根据一些业务规则从正确的部分中构建出来。你真的应该规范化这个!
但如果非要坚持的话,可以这样试试:
DECLARE @tbl TABLE(LineNumber VARCHAR(100),DocumentNumber VARCHAR(100));
INSERT INTO @tbl VALUES
('1.1/2-GM-100-10026-G01-N-1-1001','DW-2224-100-1330-1001')
,('10-FW-130-13576-B90-N-1-100-1001','DW-2224-100-1330-1001')
,('4-IA-160-12325-B10-N-1-2001','DW-2224-160-1330-2001')
,('UG-12-CS-160-160CMH306-B93-N-1-1062','DW-2224-160-1433-1062')
,('24-SL-160-12116-B12-H-1-160-MMP','DW-2224-160-1433-1062');
SELECT STUFF(LineNumber
,LEN(LineNumber)-CHARINDEX('-',REVERSE(LineNumber)) + 1
,0
,'-' + CAST('<x>' + REPLACE(DocumentNumber,'-','</x><x>') + '</x>' AS XML).value('/x[3]','varchar(max)'))
FROM @tbl AS tbl
这是结果
1.1/2-GM-100-10026-G01-N-1-100-1001
10-FW-130-13576-B90-N-1-100-100-1001
4-IA-160-12325-B10-N-1-160-2001
UG-12-CS-160-160CMH306-B93-N-1-160-1062
24-SL-160-12116-B12-H-1-160-160-MMP --Here the 160 is twice due to the test data...
转换为 XML 允许 select 您的 DocumentNumber 的第三部分很容易(但要注意 <, > and &
等禁用字符 ). STUFF
函数将此字符串放在正确的位置(反转字符串中的 first 连字符)
更新
根据您的评论,这个新查询将首先提取两个部分并进行比较。仅当行号中的倒数第二部分不等于 DocumentNumber
中的第三部分时才会插入SELECT CASE WHEN SecondLastInLineNumber=ThirdInDocumentNumber THEN LineNumber
ELSE
STUFF(LineNumber
,LEN(LineNumber)-CHARINDEX('-',REVERSE(LineNumber)) + 1
,0
,'-' + ThirdInDocumentNumber)
END AS NewLineNumber
FROM @tbl AS tbl
CROSS APPLY
(
SELECT REVERSE(CAST('<x>' + REPLACE(REVERSE(LineNumber),'-','</x><x>') + '</x>' AS XML).value('/x[2]','varchar(max)'))
,CAST('<x>' + REPLACE(DocumentNumber,'-','</x><x>') + '</x>' AS XML).value('/x[3]','varchar(max)')
) AS Parts(SecondLastInLineNumber,ThirdInDocumentNumber)
结果
1.1/2-GM-100-10026-G01-N-1-100-1001
10-FW-130-13576-B90-N-1-100-1001
4-IA-160-12325-B10-N-1-160-2001
UG-12-CS-160-160CMH306-B93-N-1-160-1062
24-SL-160-12116-B12-H-1-160-MMP
但是@Shnugo 给出的解决方案是好的。
您仍然可以尝试以下选项。
创建一个按给定字符拆分数据的函数,如下所示:
CREATE FUNCTION [dbo].[fnSplit]
(
@String NVARCHAR(4000),
@Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)
FROM Split
)
现在,使用下面的 select 语句
SELECT REPLACE
(
LineNumber,
'-'+ REVERSE(Substring(REVERSE(LineNumber),0, charindex('-',REVERSE(LineNumber)))),
'-'+
(
SELECT Data FROM [dbo].[fnSplit] (DocumentNumber,'-') Where Id=3
)+'-'+ REVERSE(Substring(REVERSE(LineNumber),0, charindex('-',REVERSE(LineNumber))))
)
FROM TableName
CREATE TABLE [dbo].[Doc](
[id] [int] IDENTITY(1,1) NOT NULL,
[LineNumber] [varchar](200) NULL,
[DocumentNumber] [varchar](200) NULL
) ON [PRIMARY]
GO
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('1.1/2-GM-100-10026-G01-N-1-1001','DW-2224-100-1330-1001')
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('10-FW-130-13576-B90-N-1-100-1001','DW-2224-100-1330-1001')
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('4-IA-160-12325-B10-N-1-2001','DW-2224-160-1330-2001')
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('UG-12-CS-160-160CMH306-B93-N-1-1062','DW-2224-160-1433-1062')
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('24-SL-160-12116-B12-H-1-160-MMP','DW-2224-160-1433-1062')
GO
SELECT
Id,
DocumentNumber,
LineNumber,
REVERSE(STUFF(REVERSE(LineNumber), CHARINDEX('-', REVERSE(LineNumber)) + 1, 0, REVERSE(REVERSE(REVERSE('-' + SUBSTRING(DocumentNumber, 9, LEN(DocumentNumber) - 18))))))
AS LineNumberInRequiredFormat
FROM [Doc]
Result
LineNumberInRequiredFormat
*********************************
1.1/2-GM-100-10026-G01-N-1-100-1001
10-FW-130-13576-B90-N-1-100-100-1001
4-IA-160-12325-B10-N-1-160-2001
UG-12-CS-160-160CMH306-B93-N-1-160-1062
24-SL-160-12116-B12-H-1-160-160-MMP