-- Given a CSV string like this:
declare @roles varchar(800)
select @roles = 'Pub,RegUser,ServiceAdmin'
-- Question: How to get roles into a table view like this:
select 'Pub'
union
select 'RegUser'
union
select 'ServiceAdmin'
发布后,我开始玩一些动态SQL。这似乎有效,但似乎使用动态SQL可能存在一些安全风险 - 对此有什么看法?
declare @rolesSql varchar(800)
select @rolesSql = 'select ''' + replace(@roles, ',', ''' union select ''') + ''''
exec(@rolesSql)
答案 0 :(得分:10)
请参阅here
的答案但基本上你会:
在您的数据库中创建此功能:
CREATE FUNCTION dbo.Split(@origString varchar(max), @Delimiter char(1))
returns @temptable TABLE (items varchar(max))
as
begin
declare @idx int
declare @split varchar(max)
select @idx = 1
if len(@origString )<1 or @origString is null return
while @idx!= 0
begin
set @idx = charindex(@Delimiter,@origString)
if @idx!=0
set @split= left(@origString,@idx - 1)
else
set @split= @origString
if(len(@split)>0)
insert into @temptable(Items) values(@split)
set @origString= right(@origString,len(@origString) - @idx)
if len(@origString) = 0 break
end
return
end
然后调用该函数并传入要拆分的字符串。
Select * From dbo.Split(@roles, ',')
答案 1 :(得分:10)
如果您正在使用SQL Server兼容级别130,那么STRING_SPLIT函数现在是最简洁的方法。
参考链接:https://msdn.microsoft.com/en-gb/library/mt684588.aspx
用法:
SELECT * FROM string_split('Pub,RegUser,ServiceAdmin',',')
RESULT:
value
-----------
Pub
RegUser
ServiceAdmin
答案 2 :(得分:5)
以下是对您的选择的详尽讨论:
答案 3 :(得分:1)
使用SQL Server内置的XML解析也是一种选择。当然,这会掩盖符合RFC-4180标准的CSV的所有细微差别。
-- Given a CSV string like this:
declare @roles varchar(800)
select @roles = 'Pub,RegUser,ServiceAdmin'
-- Here's the XML way
select split.csv.value('.', 'varchar(100)') as value
from (
select cast('<x>' + replace(@roles, ',', '</x><x>') + '</x>' as xml) as data
) as csv
cross apply data.nodes('/x') as split(csv)
如果您使用的是SQL 2016+,使用string_split
会更好,但这是在SQL 2016之前执行此操作的常用方法。
答案 4 :(得分:0)
使用BULK INSERT可以将csv文件导入到sql表中 -
答案 5 :(得分:0)
在这种情况下,我只是使用一些字符串替换将其转换为json并像表一样打开json。可能并不适合每种用例,但运行起来非常简单,并且可以处理字符串和文件。对于文件,您只需要观看换行符,大多数情况下,我会发现它是“ Char(13)+ Char(10)”
declare @myCSV nvarchar(MAX)= N'"Id";"Duration";"PosX";"PosY"
"•P001";223;-30;35
"•P002";248;-28;35
"•P003";235;-26;35'
--CSV to JSON
--convert to json by replacing some stuff
declare @myJson nvarchar(MAX)= '[['+ replace(@myCSV, Char(13)+Char(10), '],[' ) +']]'
set @myJson = replace(@myJson, ';',',') -- Optional: ensure coma delimiters for json if the current delimiter differs
-- set @myJson = replace(@myJson, ',,',',null,') -- Optional: empty in between
-- set @myJson = replace(@myJson, ',]',',null]') -- Optional: empty before linebreak
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT 0))-1 AS LineNumber, *
FROM OPENJSON( @myJson )
with (
col0 varchar(255) '$[0]'
,col1 varchar(255) '$[1]'
,col2 varchar(255) '$[2]'
,col3 varchar(255) '$[3]'
,col4 varchar(255) '$[4]'
,col5 varchar(255) '$[5]'
,col6 varchar(255) '$[6]'
,col7 varchar(255) '$[7]'
,col8 varchar(255) '$[8]'
,col9 varchar(255) '$[9]'
--any name column count is possible
) csv
order by (SELECT 0) OFFSET 1 ROWS --hide header row
答案 6 :(得分:0)
即使是接受的答案也能正常工作。但即使有数千条记录,我也能更快地获得此功能。创建下面的函数并使用。
IF EXISTS (
SELECT 1
FROM Information_schema.Routines
WHERE Specific_schema = 'dbo'
AND specific_name = 'FN_CSVToStringListTable'
AND Routine_Type = 'FUNCTION'
)
BEGIN
DROP FUNCTION [dbo].[FN_CSVToStringListTable]
END
GO
CREATE FUNCTION [dbo].[FN_CSVToStringListTable] (@InStr VARCHAR(MAX))
RETURNS @TempTab TABLE (Id NVARCHAR(max) NOT NULL)
AS
BEGIN
;-- Ensure input ends with comma
SET @InStr = REPLACE(@InStr + ',', ',,', ',')
DECLARE @SP INT
DECLARE @VALUE VARCHAR(1000)
WHILE PATINDEX('%,%', @INSTR) <> 0
BEGIN
SELECT @SP = PATINDEX('%,%', @INSTR)
SELECT @VALUE = LEFT(@INSTR, @SP - 1)
SELECT @INSTR = STUFF(@INSTR, 1, @SP, '')
INSERT INTO @TempTab (Id)
VALUES (@VALUE)
END
RETURN
END
GO
---Test like this.
declare @v as NVARCHAR(max) = N'asdf,,as34df,234df,fs,,34v,5fghwer,56gfg,';
SELECT Id FROM dbo.FN_CSVToStringListTable(@v)