none
Liste im Select-Statement übergeben RRS feed

  • Frage

  • Guten Morgen zusammen,

    gibt es eine Möglichkeit eine Datatable in ein Select-IN-Statemant zu übergeben? Quasi nach diesem Schema...

    Using con As New SqlClient.SqlConnection(_ConString)
                    Dim cmd As New SqlClient.SqlCommand("SELECT * FROM tb_USER WHERE ID IN ("& Datatable &")", con)
                    Dim da As New SqlDataAdapter(cmd)
                    da.Fill(dt)
    End Using

    Die übergebene Tabelle eine Liste mit Materialnummern aus SAP die zur Laufzeit immer neu geladen wird. Über einen DataView suche ich spezielle Materialnummern heraus und möchte diese dann an den SQL-Server übergeben. In der Vergangenheit hab ich mir einen String aus den ganzen Daten (10-20 Datensätze) zusammengebaut, bei 4000 Datensätzen wäre es etwas unschönen einen 3km langen String an die DB zu übergeben :-)

    Beste Grüße
    David

    Freitag, 24. August 2012 07:15

Antworten

  • Damit man diesen Thread als erledigt kennzeichnen kann, möchte ich hier nochmal die zusammengefasste Lösung anhand eines Beispiels vorstellen. Dies kann dann jeder für seine Anwendung individuell anpassen.

    1. müssen wir auf dem SQL-Server die Tabelle, den Typ und ein paar Datensätze haben. Das ganze sollte in etwa wie folgt aussehen. Eine Datenbank sollte bereits vorhanden sein :-)

    CREATE TABLE tb_user(
    	ID INT IDENTITY(1,1) PRIMARY KEY,
    	Vorname VARCHAR(50) NOT NULL,
    	Nachname VARCHAR(50) NOT NULL
    );
    GO
    CREATE TYPE tb_userType AS TABLE(
    	ID INT,
    	Vorname VARCHAR(50),
    	Nachname VARCHAR(50)
    );
    GO
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Holger','Schulz');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Michael','Schmidt');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Thomas','Hermann');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Dirk','Metzger');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Stefan','Rodos');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Martin','Leimbach');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Rafael','Krüger');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Sven','Hein');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Heinrich','Pezzo');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Alexander','Kollo');

    Bei einem lokalen Server und der normalen Windows-Authentifikation sollte es nun passen. Für einen speziellen Benutzer müssen noch die Berechtigungen freigegebenen werden.

    Nun habe ich eine simple Anwendung mit einem DataGridView erstellt und den folgenden Code in die Load Prozedur gelegt

    Dim dt As New DataTable
            dt.Columns.Add("UserID", GetType(Integer))
            dt.Columns.Add("Vorname", GetType(String))
            dt.Columns.Add("Nachname", GetType(String))
    
            dt.Rows.Add(1, "", "")
            dt.Rows.Add(3, "", "")
            dt.Rows.Add(6, "", "")
            dt.Rows.Add(9, "", "")
    
            Using con As New SqlClient.SqlConnection(My.Settings.TestDBConnectionString)
                Dim cmd As New SqlClient.SqlCommand("SELECT * FROM tb_User WHERE ID IN (SELECT ID FROM @MeineUser)", con)
                cmd.Parameters.AddWithValue("@MeineUser", dt)
                cmd.Parameters("@MeineUser").SqlDbType = SqlDbType.Structured
                cmd.Parameters("@MeineUser").TypeName = "tb_userType"
                Dim dt2 As New DataTable
                Dim da As New SqlClient.SqlDataAdapter(cmd)
                da.Fill(dt2)
                Me.DataGridView1.DataSource = dt2
            End Using

    Was hier passiert ist recht simpel. Ich erstelle eine Tabelle die so aussieht wie meine TYP-Tabelle auf dem SQL Server. Dort trage ich die ID und leere Namen und Nachnamen ein, da diese erstmal uninteressant sind. Im zweiten Schritt wird nach der Connection das SQL-Statement gebaut mit meiner @MeineUser Variable über welche ich gleich meine UsertTable übergebe.

    Igg. war es das nun und man kann eine ganze Tabelle an den Server übergeben und das SELECT ... IN .... Statement nutzen. Hoffe es hilft dem ein oder anderem weiter :-)

    Beste Grüße
    David



    • Als Antwort markiert David Stania Mittwoch, 29. August 2012 10:53
    Sonntag, 26. August 2012 14:48

Alle Antworten

  • bei 4000 Datensätzen wäre es etwas unschönen einen 3km langen String an die DB zu übergeben :-)

    Hallo David,

    der IN (Transact-SQL) Operator ist in Hinsicht an Werten für die Liste limitiert, siehe dort unter "Hinweis"; dort steht nur wage "hohe Anzahl", aus Erfahrung ist beim SQL Server 2005 bei ~1000 bereits Schluß.

    Andere Optionen:
    - Mit einer temporären Tabelle arbeiten und dann mit

    SELECT *
    FROM tb_User
    WHERE ID IN (SELECT ID from #myTempTable)

    abfragen.

    - Siehe Table-Valued Parameters in SQL Server 2008 (ADO.NET)


    Olaf Helper
    Blog Xing

    Freitag, 24. August 2012 07:24
  • Hi,

    i'm not sure if this is what you're asking, but if you'd want this to work, it should be something like this:

    Dim cmd As New SqlClient.SqlCommand("SELECT * FROM tb_USER WHERE ID IN ( select id from " & Datatable & ")", con)


    Regards, Nico

    Freitag, 24. August 2012 07:26
  • Hallo Olaf,

    danke für die schnelle Rückmeldung!!! Ich bin bereits über deinen Link gestolpert war mir aber im ersten Ansatz nicht sicher ob das der richtige Weg ist. Nun weiß ich erstmal wie ich da weiter komme!

    Beste Grüße
    David

    Freitag, 24. August 2012 07:34
  • Damit man diesen Thread als erledigt kennzeichnen kann, möchte ich hier nochmal die zusammengefasste Lösung anhand eines Beispiels vorstellen. Dies kann dann jeder für seine Anwendung individuell anpassen.

    1. müssen wir auf dem SQL-Server die Tabelle, den Typ und ein paar Datensätze haben. Das ganze sollte in etwa wie folgt aussehen. Eine Datenbank sollte bereits vorhanden sein :-)

    CREATE TABLE tb_user(
    	ID INT IDENTITY(1,1) PRIMARY KEY,
    	Vorname VARCHAR(50) NOT NULL,
    	Nachname VARCHAR(50) NOT NULL
    );
    GO
    CREATE TYPE tb_userType AS TABLE(
    	ID INT,
    	Vorname VARCHAR(50),
    	Nachname VARCHAR(50)
    );
    GO
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Holger','Schulz');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Michael','Schmidt');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Thomas','Hermann');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Dirk','Metzger');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Stefan','Rodos');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Martin','Leimbach');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Rafael','Krüger');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Sven','Hein');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Heinrich','Pezzo');
    INSERT INTO tb_user (Vorname, Nachname) VALUES ('Alexander','Kollo');

    Bei einem lokalen Server und der normalen Windows-Authentifikation sollte es nun passen. Für einen speziellen Benutzer müssen noch die Berechtigungen freigegebenen werden.

    Nun habe ich eine simple Anwendung mit einem DataGridView erstellt und den folgenden Code in die Load Prozedur gelegt

    Dim dt As New DataTable
            dt.Columns.Add("UserID", GetType(Integer))
            dt.Columns.Add("Vorname", GetType(String))
            dt.Columns.Add("Nachname", GetType(String))
    
            dt.Rows.Add(1, "", "")
            dt.Rows.Add(3, "", "")
            dt.Rows.Add(6, "", "")
            dt.Rows.Add(9, "", "")
    
            Using con As New SqlClient.SqlConnection(My.Settings.TestDBConnectionString)
                Dim cmd As New SqlClient.SqlCommand("SELECT * FROM tb_User WHERE ID IN (SELECT ID FROM @MeineUser)", con)
                cmd.Parameters.AddWithValue("@MeineUser", dt)
                cmd.Parameters("@MeineUser").SqlDbType = SqlDbType.Structured
                cmd.Parameters("@MeineUser").TypeName = "tb_userType"
                Dim dt2 As New DataTable
                Dim da As New SqlClient.SqlDataAdapter(cmd)
                da.Fill(dt2)
                Me.DataGridView1.DataSource = dt2
            End Using

    Was hier passiert ist recht simpel. Ich erstelle eine Tabelle die so aussieht wie meine TYP-Tabelle auf dem SQL Server. Dort trage ich die ID und leere Namen und Nachnamen ein, da diese erstmal uninteressant sind. Im zweiten Schritt wird nach der Connection das SQL-Statement gebaut mit meiner @MeineUser Variable über welche ich gleich meine UsertTable übergebe.

    Igg. war es das nun und man kann eine ganze Tabelle an den Server übergeben und das SELECT ... IN .... Statement nutzen. Hoffe es hilft dem ein oder anderem weiter :-)

    Beste Grüße
    David



    • Als Antwort markiert David Stania Mittwoch, 29. August 2012 10:53
    Sonntag, 26. August 2012 14:48