Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何根据作为varchar传递的ID列表获得结果?_C#_Sql_Sql Server_Sql Server 2008 - Fatal编程技术网

C# 如何根据作为varchar传递的ID列表获得结果?

C# 如何根据作为varchar传递的ID列表获得结果?,c#,sql,sql-server,sql-server-2008,C#,Sql,Sql Server,Sql Server 2008,我以varchar500的形式传递ids列表,基于此,需要ids记录 declare @Ids varchar(500) = '12964,12965,12966' select * from tblBooks where BookID in (@Ids) 其中BookID为varchar50。ID的数量可以是100。将@Ids转换为int会产生以下错误 转换varchar值时转换失败 “129641296512966”到数据类型int 如何查找@Id未转换为Int的结果。您可以这样编写查询

我以varchar500的形式传递ids列表,基于此,需要ids记录

declare @Ids varchar(500) = '12964,12965,12966'

select *
from tblBooks
where BookID in (@Ids)
其中BookID为varchar50。ID的数量可以是100。将@Ids转换为int会产生以下错误

转换varchar值时转换失败 “129641296512966”到数据类型int


如何查找@Id未转换为Int的结果。

您可以这样编写查询:

declare @Ids varchar(500) = '12964,12965,12966'

select *
from tblBooks
where ','+cast(BookID as varchar(500))+',' like '%,'+@Ids+',%';
但是您不想这样做,因为性能很差-查询不能使用索引

其他三种选择。使用动态SQL并将列表直接插入查询。或者使用拆分函数拆分字符串。或使用表变量:

declare @ids table (id int);
insert into @ids(id)
    select 12964 union all select 12965 union all select 12966;

select b.*
from tblBooks b
where b.BookId in (select id from @ids);
DECLARE @Ids TABLE (ID INT);
INSERT @Ids VALUES (12964),(12965),(12966);

SELECT *
FROM tblBooks
WHERE BookID in (SELECT ID FROM @Ids);
使用表变量:

declare @ids table (id int);
insert into @ids(id)
    select 12964 union all select 12965 union all select 12966;

select b.*
from tblBooks b
where b.BookId in (select id from @ids);
DECLARE @Ids TABLE (ID INT);
INSERT @Ids VALUES (12964),(12965),(12966);

SELECT *
FROM tblBooks
WHERE BookID in (SELECT ID FROM @Ids);
如果需要将其传递给过程,则可以使用表值参数:

CREATE TYPE dbo.ListOfInt AS TABLE (ID INT);
GO
CREATE PROCEDURE dbo.GetBooks @IDs dbo.ListOfInt READONLY
AS
BEGIN
    SELECT *
    FROM tblBooks
    WHERE BookID in (SELECT ID FROM @Ids);
END
GO

DECLARE @IDs dbo.ListofInt;
INSERT @Ids VALUES (12964),(12965),(12966);
EXECUTE dbo.GetBooks @Ids;
或者来自c

var table = new DataTable();
table.Columns.Add("ID", typeof(int));

// ADD YOUR LIST TO THE TABLE

using (var connection = new SqlConnection("Connection String"))
using (var command = new SqlCommand("dbo.GetBooks", connection))
{
    command.CommandType = CommandType.StoredProcedure;
    var param = new SqlParameter("@Ids", SqlDbType.Structured);
    param.TypeName = "dbo.ListofInt";
    param.Value = table;
    command.Parameters.Add(table);
    connection.Open();

    using (var reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            // do something
        }
    }
}
一旦类型就位,您甚至不需要使用存储过程。您只需调用普通查询:

using (var connection = new SqlConnection("Connection String"))
using (var command = new SqlCommand("SELECT * FROM tblBooks WHERE BookID IN (SELECT ID FROM @IDs)", connection))
{
    var param = new SqlParameter("@Ids", SqlDbType.Structured);
    param.TypeName = "dbo.ListofInt";
    param.Value = table;
    command.Parameters.Add(table);
    connection.Open();

    // ETC
}

使用String.split在c中进行拆分并将列表传递给SQL将比在SQL中进行拆分的任何方法都更有效,这是行不通的。SQL Server不会为您隐式拆分字符串,并且SQL Server中也没有内置的字符串拆分函数

如果您是通过C驱动的,则可以使用表值参数。您还可以通过Dapper Dot Net传递查询,它将自动参数化In查询

如果您真的必须在T-SQL中这样做,您还可以使用一个字符串拆分逻辑,这里是一个相对简洁的逻辑

SELECT i.value('./text()[1]', 'int') [id] into #ids 
FROM( values(CONVERT(xml,'<r>' + REPLACE(@Ids+left(@@dbts,0),',','</r><r>') +  '</r>')) ) a(_) 
CROSS APPLY _.nodes('./r') x(i)
select *
from tblBooks a
join #ids i on i.id = a.bookId
创建此函数:

CREATE FUNCTION [dbo].[SplitDelimiterString] (@StringWithDelimiter VARCHAR(8000), @Delimiter VARCHAR(8))

RETURNS @ItemTable TABLE (Item VARCHAR(8000))

AS
BEGIN
    DECLARE @StartingPosition INT;
    DECLARE @ItemInString VARCHAR(8000);

    SELECT @StartingPosition = 1;
    --Return if string is null or empty
    IF LEN(@StringWithDelimiter) = 0 OR @StringWithDelimiter IS NULL RETURN; 

    WHILE @StartingPosition > 0
    BEGIN
        --Get starting index of delimiter .. If string
        --doesn't contain any delimiter than it will returl 0 
        SET @StartingPosition = CHARINDEX(@Delimiter,@StringWithDelimiter); 

        --Get item from string        
        IF @StartingPosition > 0                
            SET @ItemInString = SUBSTRING(@StringWithDelimiter,0,@StartingPosition)
        ELSE
            SET @ItemInString = @StringWithDelimiter;
        --If item isn't empty than add to return table    
        IF( LEN(@ItemInString) > 0)
            INSERT INTO @ItemTable(Item) VALUES (@ItemInString);            

        --Remove inserted item from string
        SET @StringWithDelimiter = SUBSTRING(@StringWithDelimiter,@StartingPosition + 
                     LEN(@Delimiter),LEN(@StringWithDelimiter) - @StartingPosition)

        --Break loop if string is empty
        IF LEN(@StringWithDelimiter) = 0 BREAK;
    END

    RETURN
END
那么就这样称呼它:

declare @Ids varchar(500) = '12964,12965,12966'

select *
from tblBooks
where BookID in (SELECT * FROM dbo.SplitDelimiterString(@ids,','))

一种方法是将int转换为varchar。还有很多其他的方法

挑选* 从tblBooks 其中CASTBookID在@Ids中为varchar50


相关:

如果您的id是一个整数,为什么要尝试将其作为varchar传递?我正在传递c应用程序。您当前的计划有严重的缺陷。您确实需要帮助按原样实现它,因为您无法更改设计,还是希望有人帮助您以正确的方式实现它?OP询问如何将变量列表作为参数传递给SQL语句。他尝试使用逗号分隔的值作为第一种方法。这是一种常见且直观的首次尝试。这是首选方法。不过,您还没有展示如何从C应用程序调用它。这将是OP的下一期。@是的,我刚刚看到了,当你发表评论时,我已经在写编辑了。有趣的解决方案。也许这不是世界上最有效率的事情,但是完成这项工作的荣誉。