2 Stimmen

Fehler bei der Verwendung einer CSV-Zeichenfolge mit IN-Operator

Wenn ich den folgenden Code ausführe

declare @aaa nvarchar(10)
set @aaa='1,2,3'
Select * from Customer where CustomerId in (convert(nvarchar,@aaa,10))

Ich erhalte diesen Fehler

Msg 8114, Level 16, State 5, Line 3
Error converting data type nvarchar to bigint.

Bitte um Hilfe

7voto

KM. Punkte 98297

Sie können nicht verwenden IN mit einer cvs-Zeichenkette. Wenn Sie Sql Server 2008 haben, können Sie einen Parameter für Tabellenwerte verwenden (neu in SQL Server 2008). Richten Sie ihn ein, indem Sie den aktuellen Tabellenparametertyp erstellen:

CREATE TYPE IntTableType AS TABLE (ID bigint PRIMARY KEY)

Ihr Vorgehen wäre dann wie folgt:

Create Procedure up_TEST
    @Ids IntTableType READONLY
AS

SELECT * 
    from Customer where CustomerId in (SELECT ID FROM @Ids)

RETURN 0
GO

wenn Sie keine Tabellenwertparameter verwenden können, siehe: "Arrays und Listen in SQL Server 2008 mit tabellenwertigen Parametern" von Erland Sommarskog dann gibt es viele Möglichkeiten, eine Zeichenfolge in SQL Server aufzuteilen. Dieser Artikel befasst sich mit den Vor- und Nachteilen so ziemlich jeder Methode:

"Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" von Erland Sommarskog

Sie müssen eine Splitfunktion erstellen. So kann eine Splitfunktion verwendet werden:

SELECT
    *
    FROM YourTable                               y
    INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value

Ich bevorzuge den Ansatz der Zahlentabelle zum Aufteilen einer Zeichenkette in TSQL aber es gibt zahlreiche Möglichkeiten, Zeichenketten in SQL Server aufzuteilen, siehe den vorherigen Link, der die Vor- und Nachteile der einzelnen Möglichkeiten erläutert.

Damit die Numbers Table-Methode funktioniert, müssen Sie die Tabelle einmalig einrichten, wodurch eine Tabelle erstellt wird Numbers die Zeilen von 1 bis 10.000 enthält:

SELECT TOP 10000 IDENTITY(int,1,1) AS Number
    INTO Numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)

Sobald die Tabelle Numbers eingerichtet ist, erstellen Sie diese Splitfunktion:

CREATE FUNCTION [dbo].[FN_ListToTable]
(
     @SplitOn  char(1)      --REQUIRED, the character to split the @List string on
    ,@List     varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN 
(

    ----------------
    --SINGLE QUERY-- --this will not return empty rows
    ----------------
    SELECT
        ListValue
        FROM (SELECT
                  LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
                  FROM (
                           SELECT @SplitOn + @List + @SplitOn AS List2
                       ) AS dt
                      INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
                  WHERE SUBSTRING(List2, number, 1) = @SplitOn
             ) dt2
        WHERE ListValue IS NOT NULL AND ListValue!=''

);
GO 

Sie können die CSV-Zeichenfolge nun einfach aufteilen und in Ihrer Abfrage verwenden:

declare @aaa nvarchar(10)
set @aaa='1,2,3'
Select * from Customer where CustomerId in (SELECT ListValue FROM dbo.FN_ListToTable(',',@aaa))

1voto

David Hedlund Punkte 125085

Sie können eine CSV-Datei nicht an IN so. IN erwartet 1,2,3 no '1,2,3' Das ist ein großer Unterschied.

Wenn Sie eine CSV-Datei haben, müssen Sie eine Funktion erstellen, die eine CSV-Datei in eine Tabelle aufteilt, und das Ergebnis dieser Funktion in IN . In SQL Server ist eine solche Funktion nicht standardmäßig vorhanden.

Es gibt viele Lösungen für dieses Online-Angebot. Hier ist eine .

Auszug aus dem Link

CREATE FUNCTION dbo.SplitCSV (@CSVString VARCHAR(8000), @Delimiter CHAR(1))
RETURNS @temptable TABLE (items VARCHAR(8000))
AS

BEGIN

DECLARE @pos INT;
DECLARE @slice VARCHAR(8000);

SELECT @pos = 1;
IF LEN(@CSVString) < 1 OR @CSVString IS NULL RETURN;

WHILE @pos!= 0
BEGIN
SET @pos = CHARINDEX(@Delimiter,@CSVString);
IF @pos != 0
SET @slice = LEFT(@CSVString, @pos - 1);
ELSE
SET @slice = @CSVString;

IF( LEN(@slice) > 0)
INSERT INTO @temptable(Items) VALUES (@slice);

SET @CSVString = RIGHT(@CSVString, LEN(@CSVString) - @pos);
IF LEN(@CSVString) = 0 BREAK;
END
RETURN
END

1voto

Raj More Punkte 45539

Sie sollten eine benutzerdefinierte Funktion verwenden, um Ihre Zeichenfolge in eine Tabelle aufzuteilen und diese in der WHERE-Klausel zu verwenden

Hier ist der Code für die Funktion

DROP FUNCTION dbo.udf_ItemParse 
GO
CREATE FUNCTION dbo.udf_ItemParse 
(
    @Input VARCHAR(8000), 
    @Delimeter char(1)='|'
)
RETURNS @ItemList TABLE (
    Item VARCHAR(50) ,
    Pos int
)
AS
BEGIN

    DECLARE @Item varchar(50)
    DECLARE @StartPos int, @Length int
    DECLARE @Pos int

    SET @Pos = 0

    WHILE LEN(@Input) > 0
    BEGIN

        SET @StartPos = CHARINDEX(@Delimeter, @Input)

        IF @StartPos < 0 SET @StartPos = 0

        SET @Length = LEN(@Input) - @StartPos - 1

        IF @Length < 0 SET @Length = 0

        IF @StartPos > 0
        BEGIN
            SET @Pos = @Pos + 1
            SET @Item = SUBSTRING(@Input, 1, @StartPos - 1)
            SET @Input = SUBSTRING(@Input, @StartPos + 1, LEN(@Input) - @StartPos)
        END
        ELSE
        BEGIN
            SET @Pos = @Pos+1
            SET @Item = @Input
            SET @Input = ''
        END

        INSERT @ItemList (Item, Pos) VALUES(@Item, @Pos)
    END
    RETURN
END 
GO

So können Sie es verwenden

declare @aaa nvarchar(10)
set @aaa='1,2,3'
Select * from Customer 
where 
CustomerId in (SELECT Item From Udf_ItemParse(@aaa, ','))

0voto

Der Wert 1,2,3 konnte nicht in bigint umgewandelt werden.

Und das ist normal, weil es sich um einen nvarchar-Wert handelt, den Sie mit einer Anweisung wie dieser aufrufen möchten

Select * from Customer where CustomerId in (1,2,3)

Hier holen Sie sich drei Einträge.

Select * from Kunde wo CustomerId in ('1,2,3')

und hier versuchen Sie, ein Objekt abzurufen.

Die Operation, die Sie durchführen möchten, ist von diesem nvarchar nicht möglich

die Konvertierungsfunktion kann nur eine nvarchar-Zeichendarstellung in eine Zahlendarstellung umwandeln, und es gibt keine Zahl, die wie 1,2,3 aussieht

0voto

Michael Pakhantsov Punkte 24167
 Declare @SQL VarChar(1000)
 @SQL = 'Select * from Customer where CustomerId in (' + @aaa + ')'
 EXEC (@SQL)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X