【问题标题】:Passing two strings into a stored procedure and splitting them via specific character to perform a query将两个字符串传递到存储过程中并通过特定字符将它们拆分以执行查询
【发布时间】:2018-08-10 16:14:57
【问题描述】:

我的基本程序基本上如下所示:

create procedure zsp_selectallupceans_list
    (@UPCList nvarchar(4000),
    @EANList nvarchar(4000))
as
    select *
    from data as dd 
    where dd.UPC in (--myUPC list) or dd.EAN in (--myEAN list)

这是基本思想。现在我需要以某种方式拆分我从 C# 应用程序传递的这个字符串,它看起来像 UPC 和 EAN 列表:

 where dd.UPC in ('123','456','567') or dd.EAN in('1234','5542','412')

从 C# 应用程序传递的 UPCList 参数如下所示:

'123,456,567' and eanlist: '1234,5542,412'

我找到了一个看起来像这样的方法:

CREATE FUNCTION dbo.splitstring 
    (@stringToSplit VARCHAR(MAX))
RETURNS
    @returnList TABLE ([Name] [NVARCHAR](500))
AS
BEGIN
    DECLARE @name NVARCHAR(255)
    DECLARE @pos INT

    WHILE CHARINDEX(',', @stringToSplit) > 0
    BEGIN
        SELECT @pos  = CHARINDEX(',', @stringToSplit)  
        SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

        INSERT INTO @returnList 
            SELECT @name

        SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
    END

    INSERT INTO @returnList
        SELECT @stringToSplit

    RETURN
END

这个函数的用法如下:

SELECT * FROM dbo.splitstring('91,12,65,78,56,789')

输出是这些数字,它们被拆分并作为结果输出。

现在我只需要以某种方式将所有这些组合起来,以便我可以根据传递的参数 UPCList 和 EANList 形成正确的 where 语句

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 从 C# 中,您可以将 DataTable 用作传递给 SP 的表值参数:docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/… - 然后您可以在 SP 中拥有一个 @tablevariable,您可以使用 IN() 加入或子查询。
  • 我添加了一个额外的答案,其中包含 2 条性能改进建议。

标签: c# asp.net sql-server stored-procedures split


【解决方案1】:

如下更新您的存储过程应该可以解决问题:

create procedure zsp_selectallupceans_list
(
@UPCList nvarchar(4000),
@EANList nvarchar(4000)
)
as

select *
from data  as dd 
where dd.UPC in (SELECT * FROM dbo.SplitString(@UPCList)) OR
dd.EAN in (SELECT * FROM dbo.SplitString(@EANList))

【讨论】:

  • OR 语句将确保如果未找到 UPC 的结果,则会找到 EAN 的结果?
  • 如果发现一条记录与您表中的 UPC表中的 EAN 匹配,它将作为您的过程的结果返回,所以是的。跨度>
  • 啊哈,明白了,如果程序返回任何重复的 UPC/EAN,最有效的方法是什么?
  • 我不熟悉您的数据库架构,但此过程不应返回重复记录(即 - 如果在您的 UPC 和 EAN 列表中都找到一条记录,它只会出现一次在你的结果中)。话虽如此,如果表本身以某种方式允许重复,您可以使用SELECT DISTINCT 语句代替常规SELECT,这将确保SELECT DISTINCT 子句之后指定的所有值的唯一性。还有其他方法可以确保唯一性,我需要更多地了解您的架构以确定“最有效”的方式。
【解决方案2】:

你几乎有答案: 编译并保存 splitstring 函数,然后你的 where 子句将如下所示:

where dd.UPC in (Select Name From splitstring(--myUpcList)) or dd.EAN in (Select Name from splitstring(--myEanList)

【讨论】:

    【解决方案3】:

    这是一个基于 XML 的字符串拆分函数,这个方法比你已经找到的 SUBSTRING 方法快得多。还建议使用EXISTS 而不是IN 来提高性能,请参阅here 了解更多信息。

    CREATE FUNCTION [dbo].[SplitString]
    (
      @string nvarchar(max),
      @delimiter nvarchar(5)
    ) RETURNS @t TABLE
    (
      val nvarchar(500)
    )
    AS
    BEGIN
      declare @xml xml
      set @xml = N'<root><r>' + replace(@string,@delimiter,'</r><r>') + '</r></root>'
    
      insert into @t(val)
      select 
        r.value('.','varchar(500)') as item
      from @xml.nodes('//root/r') as records(r)
    
      RETURN
    END
    

    使用方法:

    SELECT *
    FROM data t
    WHERE EXISTS (SELECT 1 FROM dbo.SplitString(@UPCList,',') S1 WHERE t.UPC=S1.val) 
       OR EXISTS (SELECT 1 FROM dbo.SplitString(@EANList,',') S2 WHERE t.EAN=S2.val)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-03
      • 1970-01-01
      • 1970-01-01
      • 2017-09-10
      • 2014-02-26
      • 2015-09-20
      • 1970-01-01
      相关资源
      最近更新 更多