我需要编写获取字符串的存储过程。字符串中的每个字符都必须转换为int
类型,并且必须将转换后的类型插入到表中。
答案 0 :(得分:4)
如何编写UDF(http://vadivel.blogspot.com/2011/10/how-to-split-delimited-string-values-in.html)来拆分分隔的字符串然后在你的内部调用它存储过程。
CREATE FUNCTION [dbo].[SplitUsingXML]
(
@String VARCHAR(MAX),
--If your delimiter is multi character
--then change it as VARCHAR with appropriate length
@Delimiter CHAR(1)
)
RETURNS @Results TABLE
(
parsedValue VARCHAR(MAX)
)
AS
BEGIN
DECLARE @xml XML
SET @XML = N'<Content><row>' + REPLACE(@String, @Delimiter, '</row><row>') + '</row></Content>'
--If your individual value length within the CSV can be more than 25 characters
--then you might want to increase it in the below statement
--pls note it won't throw an error if its more than 25 characters
--just that it would truncate and show only the first 25 character :)
INSERT INTO @Results(parsedValue)
SELECT row.value('.','VARCHAR(25)') as parsedValue
FROM @xml.nodes('//Content/row') AS RECORDS(row)
RETURN
END
GO
--Usage
SELECT Cast(parsedValue as INT)
FROM [dbo].[SplitUsingXML] ('1,2,3,4', ',')
GO
答案 1 :(得分:3)
我在这个问题上发布的数字表解决方案将是您最有效的解决方案。 Print bullet before each sentence + new line after each sentence SQL将在我回家后修补代码
基本工作单元是内联表值函数。您可能听说过TVF以及它们如何在SQL Server中吮吸但与多语句类型有关。内联很好,因为优化器可以理解它们而不会制定糟糕的计划。
dbo.StringSplit
返回单列(varchar)表,其值根据提供的分隔符进行拆分。如果您的数据中已有数字表或快速数字生成器,则可以减少所需的代码行(派生表L0到L5)。我假设你没有。使用numbers table to split data的技术不是我的,但我相信已完成分析的SQL杰出人物。
你要求一个proc,所以我提供dbo.StringSplitToInts
来遵守,但它所做的只是用适当的参数调用TVF。您可以提取select语句并转换为内联代码或任何您需要的代码。
-- This function splits a delimited string with good performance
-- characteristics
CREATE FUNCTION dbo.StringSplit
(
@input varchar(8000)
, @delimiter char(1) = ','
)
RETURNS
table
RETURN
-- L0 to L5 simulate a numbers table
-- http://billfellows.blogspot.com/2009/11/fast-number-generator.html
WITH L0 AS
(
SELECT
0 AS C
UNION ALL
SELECT
0
)
, L1 AS
(
SELECT
0 AS c
FROM
L0 AS A
CROSS JOIN L0 AS B
)
, L2 AS
(
SELECT
0 AS c
FROM
L1 AS A
CROSS JOIN L1 AS B
)
, L3 AS
(
SELECT
0 AS c
FROM
L2 AS A
CROSS JOIN L2 AS B
)
, L4 AS
(
SELECT
0 AS c
FROM
L3 AS A
CROSS JOIN L3 AS B
)
, L5 AS
(
SELECT
0 AS c
FROM
L4 AS A
CROSS JOIN L4 AS B
)
, NUMS AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS number
FROM
L5
)
, SOURCE_DATA (ID, content) AS
(
-- This query simulates your input data
-- This implementation could be simplified as our function
-- only accepts 1 row of data but this could be applied to
-- any category of problem, not just a single line of input
SELECT 1, @input
)
, MAX_LENGTH AS
(
-- this query is rather important. The current NUMS query generates a
-- very large set of numbers but we only need 1 to maximum lenth of our
-- source data. We can take advantage of a 2008 feature of letting
-- TOP take a dynamic value
SELECT TOP (SELECT MAX(LEN(SD.content)) AS max_length FROM SOURCE_DATA SD)
N.number
FROM
NUMS N
)
, MULTI_LINES AS
(
-- This query will make many lines out a single line based on the supplied delimiter
-- Need to retain the ID (or some unique value from original data to regroup it
-- http://www.sommarskog.se/arrays-in-sql-2005.html#tblnum
SELECT
SD.ID
, LTRIM(substring(SD.content, Number, charindex(@delimiter, SD.content + @delimiter, Number) - Number)) AS lines
FROM
MAX_LENGTH
CROSS APPLY
SOURCE_DATA SD
WHERE
Number <= len(SD.content)
AND substring(@delimiter + SD.content, Number, 1) = @delimiter
)
SELECT
ML.lines
FROM
MULTI_LINES ML
GO
-- This is overkill as the function is more versatile but
-- in the spirit of delivering what was asked for, this proc
-- calls the function and casts the data to the appropriate type
CREATE PROCEDURE dbo.StringSplitToInts
(
@input varchar(8000)
, @delimiter char(1) = ','
)
AS
BEGIN
SET NOCOUNT ON
SELECT
CAST(SS.lines AS int) AS int_tokens
FROM
dbo.StringSplit(@input, @delimiter) SS
END
GO
-- Over 9000!
EXECUTE dbo.StringSplitToInts '100,200,300,500,9000'
答案 2 :(得分:1)
从我的想法:(未经测试)
转换:
select cast ( @myString as int)
将字符拆分为整数表:
create procedure aaa
@d nvarchar(max)
as
declare @i int
set @i=0
declare @t table(val int)
while @i<=len(@d)
begin
insert into @t (val) select cast (SUBSTRING(@d, i, 1) as int)
set @i=@i+1
end
答案 3 :(得分:1)
您可以使用递归CTE生成字符串中的字符位置列表:
create procedure dbo.AddInts(
@numbers varchar(max))
as
; with list as
(
select 1 as pos
where len(@numbers) > 0
union all
select pos + 1
from list
where len(@numbers) > pos
)
insert YourTable
(col1)
select cast(substring(@numbers, list.pos, 1) as int)
from list
go
答案 4 :(得分:1)
使用XML
试试这个:
DECLARE @S varchar(max), @Split char(1), @X xml
SELECT @S = '1,2,3,4,5', @Split = ','
SELECT @X = CONVERT(xml,' <root> <s>' + REPLACE(@S,@Split,'</s> <s>') + '</s> </root> ')
SELECT [Value] = T.c.value('.','varchar(20)') FROM @X.nodes('/root/s') T(c)