使用逗号分隔的值更新 MS SQL 语句

3
我正在尝试创建一个SQL Update语句,它将读取文本框字段中的逗号分隔值,并使用这些逗号分隔值更新引用ID的表(1列)。
具体来说,我有一个产品表格,我想创建一个表格,以更新该表格中的“库存”列。
我每天更新我的库存电子表格,如果我可以复制/粘贴所有产品的库存CSV并将其粘贴到文本框中,然后点击更新按钮,让我的表格实际化,那就太好了。
我不知道如何做到这一点,因为我需要引用每个产品的唯一ID,并使用相匹配的库存股票值来更新该ID。
非常感谢您提供任何想法和示例。

1
请解释以下与程序设计有关的内容,并附上数据。 - TheGameiswar
为什么不在代码中解析CSV?为什么非要在SQL中解析? - P. Kouvarakis
2
你使用的 SQL Server 版本是什么?如果是 2016,它有一个很好的函数:STRING_SPLIT https://msdn.microsoft.com/en-us/library/mt684588.aspx - MacWise
1
如果您有一个格式良好的 CSV 文件,那么使用 BULK INSERT 创建一个将该文件导入临时表的过程应该更容易,并且可以按照您想要的方式处理数据。 - Joao Araujo
如果你偏向于更为初级的方法,可以使用Excel。导入数据并使用公式来构建更新/插入语句。将这些复制粘贴到SQL中,或者你可能能够连接到外部数据源(关于最后一部分不确定)。如果你知道如何编写一些代码,你可以编写一个小程序来处理一切,只需点击一个按钮就可以完成。但是我猜你可能不会,否则你可能不会问这个问题。 - Igor
1
谢谢大家的所有输入。我正在使用SQL 2014 :( 我有一个Excel插件可以让我非常容易地完成这个任务,但是考虑到其他非管理员用户不希望直接访问SQL,因此我正在尝试通过Web界面构建相对简单的东西。 - UserSN
2个回答

0
如果您正在使用SQL Server 2016,那么您可以像我在上面的评论中所述一样使用string_split函数。
select * from string_split('1,2,3,4,5',',')

然而:

如果您使用的是早期版本的 SQL Server < 2016,则可以创建一个返回表的函数,然后从那里加入到您需要更新的表中:

CREATE FUNCTION dbo.SplitStringToValues
(
   @List NVARCHAR(MAX),
   @Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING AS
RETURN
  WITH E1(N)        AS ( SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
                         UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
                         UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1),
       E2(N)        AS (SELECT 1 FROM E1 a, E1 b),
       E4(N)        AS (SELECT 1 FROM E2 a, E2 b),
       E42(N)       AS (SELECT 1 FROM E4 a, E2 b),
       cteTally(N)  AS (SELECT 0 UNION ALL SELECT TOP (DATALENGTH(ISNULL(@List,1))) 
                         ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E42),
       cteStart(N1) AS (SELECT t.N+1 FROM cteTally t
                         WHERE (SUBSTRING(@List,t.N,1) = @Delimiter OR t.N = 0))
  SELECT Item = SUBSTRING(@List, s.N1, ISNULL(NULLIF(CHARINDEX(@Delimiter,@List,s.N1),0)-s.N1,8000))
    FROM cteStart s;
go

然后这样使用函数
SELECT * FROM SplitStringToValues('1,2,3,5',',') as t

更新:

根据您在评论中提出的要求,为了获取id旁边的下一行值,您可以像下面这样做。它使用了SQL SERVER 2012中引入的LEAD函数:

SELECT Id, Value
FROM   (SELECT 
               ROW_NUMBER() over (order by(select 1)) as cnt,
               t.item AS Id, 
               Lead(t.item) 
                 OVER ( 
                   ORDER BY (SELECT 1)) Value 
        FROM   dbo.Splitstringtovalues('10,20,30,40,50,10,20,30,40,50,60,70', ',') 
               t) 
       keyValue 
WHERE  keyValue.value IS NOT NULL 
and cnt % 2 = 1 

2
作为拆分函数来说,这不是一个好的方法。您不需要使用循环来完成此操作。有很多更好的选择。http://sqlperformance.com/2012/07/t-sql-queries/split-strings - Sean Lange
1
你在说哪些循环? - MacWise
1
在你最初的帖子中,你的函数是一个非常复杂的while循环。请记住我们可以看到编辑历史记录,因此装傻企图让我的评论看起来荒谬可笑是相当愚蠢的。 - Sean Lange
1
你已经对它进行了更改,但遗憾的是你所做的也不好。这是DelimitedSplit8K函数,最初由Jeff Moden编写,多年来由社区进行修改。不幸的是,你将varchar(8000)更改为varchar(max)。如果你阅读Jeff Moden的帖子,你会发现这绝对是一个坏主意,因为性能非常差。http://www.sqlservercentral.com/articles/Tally+Table/72993/ - Sean Lange
1
这个解决方案几乎完全来自于Jeff Moden的工作,最初出现在2011年。他进行了后续改进,并在2012年将其纳入了该文章中。如果您想了解它的工作原理和优点,那篇文章是一座信息宝库。 - btberry
显示剩余4条评论

0
如果您正在使用SQL Server 2016,则可以使用string_split函数。
select * from string_split('1,2,3,4,5',',')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接