none
Problem beim hinzufügen einer Tabellenspalte. RRS feed

  • Frage

  • Guten Tag

     

    Ich arbeite zurzeit an einem Programm für ein WM 2010 Wettbewerbsspiel.

    Nun habe ich eine SQL Datenbank angelegt mit verschiedenen tabellen.

    Nun habe ich das problem, das ich in der Tabele tbl_ma (Tabelle in welcher die Mitarbeiter mit Batch nur gespeichert sind) keine spalte mehr hinzufügen kann, welche "not Null" ist.

    Jedesmal bekomme ich eine Fehlermeldung:

     

    tbl_MA-Tabelle
    - Tabelle kann nicht geändert werden.
    Mit ALTER TABLE können nur Spalten hinzugefügt werden, die NULL-Werte enthalten können oder eine DEFAULT-Definition aufweisen. Oder die hinzugefügte Spalte ist eine identity- oder timestamp-Spalte. Falls keine der genannten Bedingungen erfüllt sind, muss die Tabelle leer sein, damit diese Spalte hinzugefügt werden kann. Die 'sf'-Spalte kann nicht der nicht leeren 'tbl_MA'-Tabelle hinzugefügt werden, da sie diese Bedingungen nicht erfüllt.

    Nun habe ich mich ein bisschen darüber schlau gemacht, und habe zwar den Fehler ( das ALTER TABLE lässt "NOT NULL" nicht zu. ), ABER habe ich nicht herausfinden können, wie ich dies im VS 2008 ändern kann, das ich wieder "NOT NULL" verwenden darf.

    Vielen dank für die Hilfe.

     

    Und ich Entschuldige mich schon jetzt, da ich nicht genau wusste wohin mit dieser Frage, da es mit VS, SQL und VB zu tuhn hat.

     

    Gruss

     

    Chris K.

    Donnerstag, 25. März 2010 13:07

Antworten

  • Hallo Chris,

    wenn bereits Daten in der Tabelle vorhanden sind (!), kannst Du ein neues Feld mit NOT NULL nur hinzufügen, wenn ein Default (Standardwert) definiert ist. Du müsstest also im Tabellen-Designer einen Standardwert setzen, z.B. 0.

    Alternative wäre über T-SQL, dann könntest Du das Feld zunächst mit NULL hinzufügen, die vorhandenen Datensätze auf einen gewünschten Wert ändern (z.B. auch abhängig der vorhandenen Daten) und anschließend das Feld auf NOT NULL ändern. Beispiel:

    CREATE TABLE #test (id int IDENTITY(1,1));

    INSERT INTO #TEST DEFAULT VALUES;

    GO

    -- Per Update

    ALTER TABLE #test

    ADD sf int NULL;

    GO

    UPDATE #test

    SET sf = 0

    WHERE sf IS NULL;

    GO

    ALTER TABLE #test

    ALTER COLUMN sf int NOT NULL;

     

    -- Per Default Wert

    ALTER TABLE #test

    ADD sf2 int NOT NULL DEFAULT(0);

     

    SELECT *

    FROM #test;

     

    GO

    DROP TABLE #test;

     


    Olaf Helper ----------- * cogito ergo sum * errare humanum est * quote erat demonstrandum * Wenn ich denke, ist das ein Fehler und das beweise ich täglich http://olafhelper.over-blog.de
    Donnerstag, 25. März 2010 15:12
  • Hallo Chris,

    wenn Du eine Spalte mit NOT NULL erstellen willst,
    so mußt Du für die Spalte einen Standardwert (DEFAULT) angeben,
    denn sonst würden alle bestehenden Zeilen die NOT NULL Regel verletzen.

    Im Designer (Visual STudio oder Management Studio) findest Du es
    unter den Eigenschaften als "Standardwert oder -bindung".

    Via T-SQL:

    CREATE TABLE tbl_Ma (
    	id int not null primary key);
    	
    -- Spalte die NULL Werte zulässt
    ALTER TABLE tbl_Ma ADD SpalteMitNull int NULL;
    -- Spalte ohne NULL-Werte und einem (benannten) Standardwert
    ALTER TABLE tbl_Ma ADD SpalteOhneNullMitDefault int NOT NULL
    	CONSTRAINT DF_tbl_Ma_SpalteOhneNullMitDefault DEFAULT (0);
    

    Der angegebene Standardwert muß dem Datentyp entsprechen bzw. in ihn konvertiert werden können.

    Gruß Elmar

    Donnerstag, 25. März 2010 15:18
    Beantworter

Alle Antworten

  • Hallo Chris,

    wenn bereits Daten in der Tabelle vorhanden sind (!), kannst Du ein neues Feld mit NOT NULL nur hinzufügen, wenn ein Default (Standardwert) definiert ist. Du müsstest also im Tabellen-Designer einen Standardwert setzen, z.B. 0.

    Alternative wäre über T-SQL, dann könntest Du das Feld zunächst mit NULL hinzufügen, die vorhandenen Datensätze auf einen gewünschten Wert ändern (z.B. auch abhängig der vorhandenen Daten) und anschließend das Feld auf NOT NULL ändern. Beispiel:

    CREATE TABLE #test (id int IDENTITY(1,1));

    INSERT INTO #TEST DEFAULT VALUES;

    GO

    -- Per Update

    ALTER TABLE #test

    ADD sf int NULL;

    GO

    UPDATE #test

    SET sf = 0

    WHERE sf IS NULL;

    GO

    ALTER TABLE #test

    ALTER COLUMN sf int NOT NULL;

     

    -- Per Default Wert

    ALTER TABLE #test

    ADD sf2 int NOT NULL DEFAULT(0);

     

    SELECT *

    FROM #test;

     

    GO

    DROP TABLE #test;

     


    Olaf Helper ----------- * cogito ergo sum * errare humanum est * quote erat demonstrandum * Wenn ich denke, ist das ein Fehler und das beweise ich täglich http://olafhelper.over-blog.de
    Donnerstag, 25. März 2010 15:12
  • Hallo Chris,

    wenn Du eine Spalte mit NOT NULL erstellen willst,
    so mußt Du für die Spalte einen Standardwert (DEFAULT) angeben,
    denn sonst würden alle bestehenden Zeilen die NOT NULL Regel verletzen.

    Im Designer (Visual STudio oder Management Studio) findest Du es
    unter den Eigenschaften als "Standardwert oder -bindung".

    Via T-SQL:

    CREATE TABLE tbl_Ma (
    	id int not null primary key);
    	
    -- Spalte die NULL Werte zulässt
    ALTER TABLE tbl_Ma ADD SpalteMitNull int NULL;
    -- Spalte ohne NULL-Werte und einem (benannten) Standardwert
    ALTER TABLE tbl_Ma ADD SpalteOhneNullMitDefault int NOT NULL
    	CONSTRAINT DF_tbl_Ma_SpalteOhneNullMitDefault DEFAULT (0);
    

    Der angegebene Standardwert muß dem Datentyp entsprechen bzw. in ihn konvertiert werden können.

    Gruß Elmar

    Donnerstag, 25. März 2010 15:18
    Beantworter
  • Vielen Vielen Dank!


    mit dem Standart wert eingeben und dan in NOT NULL ändern hat perfekt funktioniert!

     

    Nun hätte ich noch eine Frage.

    Erklährung:

    In der tbl_MA (Mitarbeiter tabelle) ist Vorname, Nachname, Batchnr. und das Passwort definiert.
    am Anfang ist das Passwort = die Batchnr.

    Nun soll aber bei der ersten Anmeldung im Programm überprüft werden, ob Passwort = Batchnr ist.
    Fals dies der Fall sein sollte, wird der User aufgefordert sein Passwort zu ändern.

    -------------------------------------------------------------------------------------------------

    Dies mit der Überprüfung habe ich hingekriergt.
    jedoch bei der Änderung des passworts komme ich nicht weiter.

    Ich weiss, dass ich mit " INSERT INTO [TABELLE] SPALTE '" WERT "' " werte in spalten eingeben kann.
    Aber ich will, das nur bei diesem usert das Passwort geändert wird, nach seinen angaben.

     

    Vielen Dank

     

    Chris Kaiser

     

    Donnerstag, 25. März 2010 16:01
  • Das geht mit dem Update Befehl, z.B.

    UPDATE  tbl_MA

    SET Passwort = ...

    WHERE ...


    Olaf Helper ----------- * cogito ergo sum * errare humanum est * quote erat demonstrandum * Wenn ich denke, ist das ein Fehler und das beweise ich täglich http://olafhelper.over-blog.de
    Donnerstag, 25. März 2010 17:25
  • Guten Tag

    Vielen Dank für die Hilfe! =)

    Ich habe es mit diesem Code versucht:

     

    command.CommandText = "UPDATE [tbl_MA] SET Passwort = '" & mtb_newpw.Text & "' WHERE [tbl_MA] Nachname = '" & Start.tb_nachname.Text & "' AND Vorname = '" & Start.tb_vorname.Text & "' AND Nachname = '" & Start.tb_nachname.Text & "' AND Batchnr = '" & Start.mtb_passwort.Text & "'"

    Jedoch funktioniert dies nicht ganz,

    denn er will das in der maskedtextbox eingebene passwort nicht in die tabelle schreiben.

    (mtb_newpw ist eine masked TextBox, Start.****.Text sind TextBoxen auf einer anderen Form,welche offen ist.)

    Freitag, 26. März 2010 07:34
  • Hallo Chris,

    zunächst solltest Du nicht mit Zeichenverkettung arbeiten, schon gar nicht in kritischen Bereichen
    wie Kennwörtern, denn damit öffnest Du SQL Injection Tür und Tor.

    Und auch ohne den Teufelan die Wand zu malen, kriegst Du schon Probleme,
    wenn ein Anführungszeichen in einem Wert vorkommt (z. B. ein Nachname wie O'Malley).
    Und man verliert auch schnell den Überblick, was Dir anscheinend passiert ist,
    da Du Nachname zweimal zuweist.

    Eine bessere Variante (für den SqlClient):

    ' Namen mit @...Start entsprechen den Originalwerten 
            command.CommandText = "UPDATE [tbl_MA] SET Passwort = @Passwort " & _
    	         "WHERE Nachname = @NachnameStart AND Vorname = @VornameStart AND Batchnr = @BatchnrStart;"
    ' TODO: Datentypen und Längenangaben entsprechend Tabellendefinition anpassen
    	command.Parameters.Add("@Passwort", SqlDbType.NVarchar, 40).Value = mtb_newpw.Text
    	command.Parameters.Add("@NachnameStart", SqlDbType.NVarchar, 40).Value = Start.tb_nachname.Text
    	command.Parameters.Add("@VornameStart", SqlDbType.NVarchar, 40).Value = Start.tb_vorname.Text
    	command.Parameters.Add("@BatchnrStart", SqlDbType.NVarchar, 40).Value = Start.mtb_passwort.Text
    
    Wobei es hier günstiger und sicherer wäre, in der WHERE Bedingung auf den Primärschlüssel
    der Tabelle zurückzugreifen, den Du bereits bei der Abfrage der Daten ermittelt haben solltest.
    Womit die WHERE Klausel nicht nur einfacher, sondern auch verwechslungssicher ausgeführt wird.

    Im übrigen ist für ein Kennwort eine Textbox mit  UseSystemPasswordChar ausreichend,
    die MaskedTextBox bringt dort keinen Mehrwert.

    Gruß Elmar

     

    Freitag, 26. März 2010 08:34
    Beantworter
  • Hallo Chris,

    Jedoch funktioniert dies nicht ganz

    Das ist nicht gerade eine wirklich hilfreiche Aussage. Was funktioniert nicht, gibt es eine Fehlermeldung, wird der Datensatz nicht aktualisiert oder ... ?

    In der WHERE Klausel solltest Du entweder einen Punkt zwischen Tabellen- und Feldnamen setzen oder den Tabellennamen ganz weg lassen.

    Command.CommandText = "UPDATE [tbl_MA] " & _

                          "SET Passwort = '" & mtb_newpw.Text & "' " & _

                          "WHERE Nachname = '" & Start.tb_nachname.Text & "' " & _

                                 "AND Vorname = '" & Start.tb_vorname.Text & "' " & _

                                 "AND Nachname = '" & Start.tb_nachname.Text & "' " & _

                                 "AND Batchnr = '" & Start.mtb_passwort.Text & "'"

    Und:

    SET Passwort = '" & mtb_newpw.Text

    Du speicherst allen Ernstes das Passwort unverschlüsselt / nicht als Hash ab? Oh, oh.

     

     

     


    Olaf Helper ----------- * cogito ergo sum * errare humanum est * quote erat demonstrandum * Wenn ich denke, ist das ein Fehler und das beweise ich täglich http://olafhelper.over-blog.de
    Freitag, 26. März 2010 08:34
  • Guten Morgen Olaf

    Keine Fehlermeldung. Jedoch jetzt als ich bei WHERE das die Tabelle entfernt habe, hat es funktioniert! =)

    Vielen Dank!

     

    Und wegen der PasswortVerschlüsselung, das passwort ist nicht sehr extrem wichtig, es geht mehr darum, dass man nicht gleich anfängt für andere Leute Wetttipps abzugeben.

    Aber, der Hauptgrund ist, das ich nicht weiss, wie dies funktioniert. Denn ich habe mir in den letzten 3 Tagen im Schnellgang den einfachen umgang mit SQL Befehlen, so einigermassen anzueignen versucht.

    Jedoch, falls Du Zeit und Lust hättest, es mir zu erklähren, währe ich natürlich sehr erfreut!

     

    Mit Freundlichen Grüssen

     

    Chris Kaiser

     

    Freitag, 26. März 2010 09:15
  • OK.

    So wie ich das nun interpretiert habe, setz er mir nicht nur das Passwort sondern auch gleich Vornamen, Nachnamen und Batchnr. nach den Angaben in der Start Form.

    Richtig, oder habe ich das falsch verstanden?

     

    Gruss

    Chris Kaiser

    Freitag, 26. März 2010 09:49
  • Vorname, Nachname und Batchnummer sind nur die Filterbedingungen (WHERE), um den zu aktualisierenden Datensatz zu ermittlen; die Werte werden nicht gesetzt. Nur die Felder in der SET Anweisung werden aktualisiert.

    Das setzt aber auch voraus, das die drei Felder zusammen Deinen Primary Key darstellen und somit auch eindeutig sind. Üblicherweise verwendet man nicht einen solchen zusammengesetzten "Natural Key", sondern verwendet eine ID (z.B. als IDENTITY die automatisch vorlaufend vergeben wird), um Daten eindeutig zu identifizieren.


    Olaf Helper ----------- * cogito ergo sum * errare humanum est * quote erat demonstrandum * Wenn ich denke, ist das ein Fehler und das beweise ich täglich http://olafhelper.over-blog.de
    Freitag, 26. März 2010 10:04
  • Solch eine ID ist natürlich vorhanden =)

    und setzt sich automatisch. (1 aufwärts zählend).

     

    Aber ich verstehe diesen Code noch nicht ganz:

    command.Parameters.Add("@Passwort", SqlDbType.NVarchar, 40).Value = mtb_newpw.Text

    was macht der für eine Parameter übergabe? ist das einfach eine Aktuallisierung?

     

    Tut mir leid, wenn ich nicht gleich verstehe. Ich bin kein richtiger Programmierer. Sondern im Netzwerk und Server berreich tätig. JEdoch habe ich eine VB schulung gehabt und habe diese Arbeit übernommen.

    Vielen Dank für die Gedult.

     

     

    Freitag, 26. März 2010 10:31
  • Das siehst Du, wenn Du Dir noch mal den Code von Elmar ansiehst, sollte es klarer werden

    Command.CommandText = "UPDATE [tbl_MA] " & _

                          "SET Passwort = @Passwort " & _

                          "WHERE Nachname = @NachnameStart " & _

                                "AND Vorname = @VornameStart " & _

                                "AND Batchnr = @BatchnrStart;"

    In dem SQL Statement werden Parameter verwendet, die beginnen mit dem @ (z.B. @Passwort). Mit dem Parameters.Add wird der Wert für den Parameter gesetzt. Kann man sich so vorstellen, das die Parameter durch die Werte (wie oben mtb_newpw.Text) ersetzt werden, wobei die angesprochenen Besonderheit wie Hochkomma im Text berücksichtigt werden.

     


    Olaf Helper ----------- * cogito ergo sum * errare humanum est * quote erat demonstrandum * Wenn ich denke, ist das ein Fehler und das beweise ich täglich http://olafhelper.over-blog.de
    Freitag, 26. März 2010 10:58
  •  

    Ok nun habe ich es einigermassen verstanden =)

    und habe es erfolgreich in mein Programm implementiert!

    Vielen Dank!

     

    Jetz bleibt noch die Frage, wie kann ich das passwort verschlüsseln?

    Freitag, 26. März 2010 12:23
  • Langsam läuft es doch etwas Off Topic ...

    Zum einen gibt es zum Verschlüsseln Methoden in .NET; such einfach mal im Visual Basic Forum danach, da war letztens ein Beitrag dazu. Dann kannst Du das Passwort gleich bereits verschlüsselt an den Sql Server übertragen; das wird das sicherste sein.

    Passwörter speichert man i.d.R nur als Hashwert ab, damit man es nicht zurück-schlüsseln kann (auch Du als Entwickler der App nicht). Auch zur Hash-Wert Bildung gibt es Methoden in .NET; such mal nach HASH + MD5 oder SHA1.

    Der Sql Server bietet dazu auch Funktionen, das heisst aber, das Du das Passwort zunächst in Klartext übertragen musst; das verringert schon mal die Sicherheit, weil man das z.B. mit dem SQL Profiler protokollieren könnte.

    DECLARE @Hash as varbinary(8000)

    SET @Hash = 0x0CBC6611F5540BD0809A388DC95A615B

     

    -- Hash-Wert ermitteln

    SELECT HashBytes('MD5', 'Test')

     

    -- Prüfen, ob Passwort stimmt

    SELECT CASE WHEN @Hash = HashBytes('MD5', 'Test')

                THEN 'Passwort stimmt'

                ELSE 'Passwort stimmt nicht'

                END AS PwdValidierung

     


    Olaf Helper ----------- * cogito ergo sum * errare humanum est * quote erat demonstrandum * Wenn ich denke, ist das ein Fehler und das beweise ich täglich http://olafhelper.over-blog.de
    Freitag, 26. März 2010 12:45
  • Gut, dann werde ich mich mal da umschauen =)

     

    Vielen vielen Dank für die grosse Hilfe und die Geduld!

     

    Mit freundlichen Grüssen

     

    Chris Kaiser

    Freitag, 26. März 2010 12:48