我在一个数据库表的单个元素中有以下数据:
Port Jefferson Station, NY 11776-2598
Northport, NY 11768
Garden City, NY 11530
我试图将每行分成一个新表,其中包含一个城市字段,一个州字段和一个邮政编码字段。
我正在运行一个脚本,其中包含以下代码来获取City值:
Create function [dbo].[fnBuildCityState](@AddressCity varchar(40))
RETURNS @NameTable TABLE
(
City VARCHAR(255),
State VARCHAR(255),
Zip VARCHAR(255)
)
as
BEGIN
-- Index and word variables.
DECLARE @AccountNameEndIndex INT;
DECLARE @FirstWordEndIndex INT;
DECLARE @SecondWordEndIndex INT;
DECLARE @ThirdWordEndIndex INT;
DECLARE @FirstWord NVARCHAR(8);
DECLARE @SecondWord NVARCHAR(50);
DECLARE @ThirdWord NVARCHAR(50);
SET @AddressCity = RTRIM(ISNULL(@AddressCity,'No Address, City ZipCode'))
if (LEN(@AddressCity)<3)
BEGIN
SET @AddressCity = 'No Address, City ZipCode'
END
-- Get the last index.
SET @AccountNameEndIndex = LEN(@AddressCity) - 1;
-- Get the first word.
SET @FirstWordEndIndex = CHARINDEX(',', @AddressCity, 0);
SET @FirstWord = SUBSTRING(@AddressCity, 0, @FirstWordEndIndex);
INSERT INTO @NameTable (City, State, Zip)
VALUES (@FirstWord, @SecondWord, @ThirdWord)
RETURN
END
当我运行代码并查看结果表时,我看到了如下输出:
City State Zip
Port Jef NULL NULL
Northpor NULL NULL
Garden C NULL NULL
返回输入中逗号所在位置的索引的那行代码是
SET @FirstWordEndIndex = CHARINDEX(',', @ addressity, 0);
无论逗号在字符串中的哪个位置,它似乎总是返回值8。
知道为什么吗?
您的问题的具体答案是因为您将@FirstWord
定义为NVARCHAR(8)
,因此它只包含最多8个字符。
但更大的问题是你为什么要尝试做那个RBAR?SQL是基于集合的是有原因的…你可以构建一个查询来完成你需要的一切,例如:
SELECT b.City, C.[State], c.ZipCode
FROM (
VALUES
('Port Jefferson Station, NY 11776-2598'),
('Northport, NY 11768'),
('Garden City, NY 11530')
) x ([Address])
CROSS APPLY (
VALUES
(CHARINDEX(',', x.[Address], 0))
) a (FirstComma)
CROSS APPLY (
VALUES
(SUBSTRING(x.[Address],1,a.FirstComma-1)
, SUBSTRING(x.[Address],a.FirstComma+2,LEN(x.[Address])))
) b (City,SecondString)
CROSS APPLY (
VALUES
(SUBSTRING(b.SecondString,1,2)
, SUBSTRING(b.SecondString,4,LEN(b.SecondString)))
) c ([State],ZipCode);
的回报:
请尝试以下解决方案。
它基于标记化而不是字符串解析。
/p> 在解析字符串时,我倾向于使用JSON 结果 如果你想使用作为TVF-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, tokens VARCHAR(100));
INSERT @tbl (tokens) VALUES
('Port Jefferson Station, NY 11776-2598'),
('Northport, NY 11768'),
('Garden City, NY 11530');
-- DDL and sample data population, end
DECLARE @separator CHAR(1) = ',';
SELECT t.*
, city = c.value('(/root/r[1]/text())[1]', 'VARCHAR(50)')
, state = LEFT(TRIM(c.value('(/root/r[2]/text())[1]', 'VARCHAR(50)')), 2)
, zip = SUBSTRING(TRIM(c.value('(/root/r[2]/text())[1]', 'VARCHAR(50)')), 3, 50)
FROM @tbl AS t
CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' +
REPLACE(tokens, @separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t1(c);
ID 标记 城市国家 zip 1 纽约杰弗逊港车站11776-2598 纽约 杰弗逊港车站 纽约 11776-2598 2 Northport,纽约11768 Northport 纽约 11768 表类>3 花园城市,纽约11530 花园城市 纽约 11530 Select City = JSON_VALUE(JS1,'$[0]')
,State = JSON_VALUE(JS2,'$[0]')
,ZIP = JSON_VALUE(JS2,'$[1]')
From YourTable A
Cross Apply (values ('["'+replace(Address,',','","')+'"]') ) B(JS1)
Cross Apply (values ('["'+replace(ltrim(JSON_VALUE(JS1,'$[1]')),' ','","')+'"]') ) C(JS2)
City State ZIP
Port Jefferson Station NY 11776-2598
Northport NY 11768
Garden City NY 11530
Declare @AddressCity varchar(max) = 'Port Jefferson Station, NY 11776-2598'
Select City = JSON_VALUE(JS1,'$[0]')
,State = JSON_VALUE(JS2,'$[0]')
,ZIP = JSON_VALUE(JS2,'$[1]')
From (values ('["'+replace(@AddressCity,',','","')+'"]') ) A(JS1)
Cross Apply (values ('["'+replace(ltrim(JSON_VALUE(JS1,'$[1]')),' ','","')+'"]') ) B(JS2)