Laden...

Dynamisches SQL-Statement mit Parameter realisieren

Erstellt von jptest vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.707 Views
J
jptest Themenstarter:in
9 Beiträge seit 2008
vor 15 Jahren
Dynamisches SQL-Statement mit Parameter realisieren

verwendetes Datenbanksystem: SQL Server 2005

Hallo zusammen,

ich möchte ein SQL-Statement zusammenbasteln, habe jedoch keine Ahnung ob ich auf dem richtigen Weg bin. Die Idee ist, dass wenn der übergebene Wert NULL oder 0 ist, der Parameter dann nicht berücksichtigt wird im SQL Statement.

Beim Aufruf der GetBenutzer-Methode m_ds = m_con.GetBenutzer(1, null, null) soll das SQL-Statement anschliessend wie folgt aussehen "SELECT* FROMBenutzer WHERE id = @ID"

So bin ich vorgegangen (kein schöner Code, ich weisse, bin halt relativ noch ein Newbie 🙂) :

        public MediaDataset GetBenutzer(int id, string name, string vorname)
        {
            SqlConnection conn = getConnection();
            MediaDataset ds = new MediaDataset();
            
            SqlDataAdapter adapter = new SqlDataAdapter();
            SqlCommand cmd = new SqlCommand();
            cmd = new SqlCommand("select * from Benutzer where " + cmd.Parameters.ToString(), conn);

            if (id != 0)
            {
                SqlParameter param = new SqlParameter();
                param.ParameterName = "@ID";
                param.Value = id;

                cmd.Parameters.Add(param);
            }

            if (name != null && name != string.Empty)
            {
                SqlParameter param = new SqlParameter();
                param.ParameterName = "@Name";
                param.Value = name;

                cmd.Parameters.Add(param);
            }

            if (vorname!= null && vorname!= string.Empty)
            {
                SqlParameter param = new SqlParameter();
                param.ParameterName = "@vorname";
                param.Value = vorname;

                cmd.Parameters.Add(param);
            }

            adapter.SelectCommand = cmd;
            adapter.Fill(ds);
            conn.Close();
            return ds;
        }

Ich hoffe mir kann da jemand weiterhelfen, möglichst mit Bespielcode wenn's geht.

MfG Johannes

1.378 Beiträge seit 2006
vor 15 Jahren

Wo genau ist dein Problem?

Lg XXX

J
jptest Themenstarter:in
9 Beiträge seit 2008
vor 15 Jahren

Durch denn obenstehenden Code möchte ich ein SQL-Staement zusammenbasteln und mein Dataset abfüllen.

Wenn ich beim Aufruf von GetBenutzer(..) NULLS mitgebe, sollen jene Parameter mit den NULL-Werten (im unteren Beispiel betrifft dies Name und Vorname) nicht beachten und im SQL-Statement nur jene Paramater einschliessen, wo auch ein richtiger Wert mitgegeben wurde (in diesem Falle ID)

Und mein Problem ist. dass mein Code nicht funktioniert.

3.511 Beiträge seit 2005
vor 15 Jahren

cmd = new SqlCommand("select * from Benutzer where " + cmd.Parameters.ToString(), conn);

Das funktioniert so nicht. Der String der dabei rauskommt sieht dann in etwas so aus


select * from Benutzer where System.Data.SqlClient.SqlParameterCollection

Du musst das SQL schon dynamisch zusammen bauen

In etwas muss es so laufen


string cmdText = "select * from Benutzer where 1=1";
if (id != 0)
{
  cmdText += " and ID = @ID";
  cmd.Parameters.AddWithValue("ID", id);
}
if (name != null)
{
  cmdText += " and Name = @Name";
  cmd.Parameters.AddWithValue("Name", name);
}
// usw...

[Edit]
Bei sowas

Und mein Problem ist. dass mein Code nicht funktioniert

wäre es immer sehr hilfreich, wenn man gleich mit angibt, was nicht funktioniert.
Wobei das in deinem Falle das SQL ist.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

L
120 Beiträge seit 2007
vor 15 Jahren

und um ein bisschen platz zu sparen 😉

cmd.Parameters.Add(new SqlParameter("@ID", id));

anstatt

SqlParameter param = new SqlParameter();
param.ParameterName = "@ID";
param.Value = id;

            cmd.Parameters.Add(param);
J
jptest Themenstarter:in
9 Beiträge seit 2008
vor 15 Jahren

Danke Khalid, es funktioniert, nur taucht nun folgende Exception auf:

Must declare the scalar variable "@ID",

Habe übrigens dein Snippet angepasst, ist es nicht eher so richtig (@ bei Zuweisung):

if (name != null && name != string.Empty)
            {
                cmdText += " and Name = @Name";
                cmd.Parameters.AddWithValue("@Name", name);
            }

Ok, werde meinen Fehlerbericht das nächste Mal ein bisschen ausführlicher schreiben, wäre wohl besser.

T
708 Beiträge seit 2008
vor 15 Jahren

Must declare the scalar variable "@ID",

Das ist sozusagen die Allzweck-Fehlermeldung von SQL 😉
Es muss nicht an der Variable selbst liegen. Es kann auch an jeder Stelle des Codes ein Fehler vorgekommen sein.

Am besten schreibst du dein fertiges SQL-Statement, bevor du es dem Adapter übergibst, in eine Textdatei und schaust es dir dort an.

Das sollte die Fehlersuche vereinfachen.

J
jptest Themenstarter:in
9 Beiträge seit 2008
vor 15 Jahren

Ok, danke. Hab aber noch einen Workaround um diese Variablen gefunden, gibt es an folgender Version etwas auszusetzen❔

if (id != 0)
{
cmdText += " and ID =" + id;            
}

anstatt so

if (id != 0)
{
cmdText += " and ID = @ID";
cmd.Parameters.AddWithValue("@ID", id);
}
3.511 Beiträge seit 2005
vor 15 Jahren

Das ist MS SQL, da gehört kein @ in den Parameternamen. Nur


cmd.Parameters.AddWithValue("ID", id);

Im SQL Profile kann man das immer wunderbar sehen.

@Lecrell
AddWithValue ist noch kürzer 😉

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

3.511 Beiträge seit 2005
vor 15 Jahren

gibt es an folgender Version etwas auszusetzen❔

Ja 🙂

Benutze immer Parameter! Es gibt viele Gründe warum, die ich jetzt nicht alle aufzählen will, aber der bekannteste ist: SQL Injection vorbeugen.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

J
jptest Themenstarter:in
9 Beiträge seit 2008
vor 15 Jahren

Hehe, ok. Ich würde ja gerne deine Variante nehmen wenn es denn auch funktionieren würde. 😉

Fehler: Must declare the scalar variable "@ID",

Wenn ich dem SQL-Statement noch wie folgt gestalte


adapter.SelectCommand = new SqlCommand("declare @ID int select * from Benutzer where 1=1" + cmdText, conn);

wirft es zwar keine Exception, aber das Dataset ist dann halt einfach leer.

3.511 Beiträge seit 2005
vor 15 Jahren

Zeig mal bitte den Code.

Ich denke mal, das der Parameter für @ID nicht gesetzt ist.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

J
jptest Themenstarter:in
9 Beiträge seit 2008
vor 15 Jahren
public MediaDataset GetBenutzer(int id, string name, string passwort, string sicherheitsfrage, string sicherheitsantwort)
{
            SqlConnection conn = getConnection();
            SqlDataAdapter adapter = new SqlDataAdapter();
            SqlCommand cmd = new SqlCommand();

            MediaDataset ds = new MediaDataset();
            string cmdText = "";

            if (id != 0)
            {
                cmdText += " and ID = @ID";
                cmd.Parameters.AddWithValue("ID", id);
            }

            if (name != null && name != string.Empty)
            {
                cmdText += " and Name = @Name";
                cmd.Parameters.AddWithValue("Name", name);
            }

            if (passwort != null && passwort != string.Empty)
            {
                cmdText += " and Passwort = @Passwort";
                cmd.Parameters.AddWithValue("Passwort", passwort);
            }

            if (sicherheitsfrage != null && sicherheitsfrage != string.Empty)
            {
                cmdText += " and Sicherheitsfrage = @Sicherheitsfrage";
                cmd.Parameters.AddWithValue("Sicherheitsfrage", sicherheitsfrage);
            }

            if (sicherheitsantwort != null && sicherheitsantwort != string.Empty)
            {
                cmdText += " and Sicherheitsantwort = @Sicherheitsantwort";
                cmd.Parameters.AddWithValue("Sicherheitsantwort", sicherheitsantwort);
            }

            adapter.SelectCommand = new SqlCommand("declare @ID int select * from Benutzer where 1=1" + cmdText, conn);
            adapter.Fill(ds.Benutzer);
            conn.Close();
            return ds;
}
3.511 Beiträge seit 2005
vor 15 Jahren

Ist dieses "declare @ID int" nur ausversehen drin geblieben? Auf jeden Fall muss das da weg.

[Edit]
Noch etwas:
Du schreibst andauernd


if (name != null && name != String.Empty)

Kürzer und übersichtlicher(IMHO) geht


if (!String.IsNullOrEmpty(name))

Aber das nur so nebenbei

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

J
jptest Themenstarter:in
9 Beiträge seit 2008
vor 15 Jahren

Ist dieses "declare @ID int" nur ausversehen drin geblieben?

War noch von meinem vorherigen Versuch.

3.511 Beiträge seit 2005
vor 15 Jahren

Schau dir mal im SQL Profiler genau an, was am SQL Server ankommt. Bzw. welche Parameter da überhaupt ankommen. Und poste dann mal bitte den SQL Befehl der am Profiler ankommt.

Ich sehe da gerade kein Fehler und ich mach das häufiger auf die Art und Weise. Da klappt das eigentlich immer...

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

J
jptest Themenstarter:in
9 Beiträge seit 2008
vor 15 Jahren

moin,

folgendes kommt beim SQL-Server an:

select * from Benutzer where 1=1 and ID = @ID
3.511 Beiträge seit 2005
vor 15 Jahren

OK, ich hab dir ein Testprojekt angehängt.

Da gehe ich exakt so vor wie du. Ich sehe den Fehler ehrlich gesagt nicht.

In der ZIP ist auch eine SQL Datei, die dir die Testdatenbank plus Tabelle und Daten anlegt.

Pfade und ConnectionString müssen natürlich ggf. angepasst werden.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)