Announcement

Collapse
No announcement yet.

Trigger und Client Cursor bei Update

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Trigger und Client Cursor bei Update

    Hallo

    Ich habe ein TAdoDataSet das auf eine einzelne Tabelle verweist (CommandType = cmdTable, CursorLocation = clUseClient, CommandText = t_style). Auf der Tabelle liegt ein Update Trigger der ein Feld in einer anderen Tabelle (t_Test)updatet.

    vereinfachte Definition des Triggers:

    create trigger tr_upd_style
    on t_style
    for update
    as
    if update(c_style_name)
    BEGIN
    update t_Test SET info='Hallo' WHERE ID = 1
    END

    Über ein TDBEdit verändere ich einen Wert aus dieser Tabelle. Wenn der Datensatz dann gespeichert werden soll, erhalte ich die folgende Fehlermeldung:

    <PRE>
    (#-2147467259
    Error: Key column information is insufficient or incorrect. Too many rows were affected by update.
    Source: Microsoft Cursor Engine
    SQLState:
    NativeError: 1009)
    </PRE>

    Wenn ich einen Server seitigen Cursor verwende klappt das Update. Aus anderen Gründen kann ich aber nur den Client seitigen Cursor verwenden.

    Wenn ich den Trigger lösche, dann funktioniert alles wie es sollte.

    Es kommt MSSQL2000 und Delphi 5.01 zum Einsatz.

    Für jede Hilfe dankbar --> Lothar

  • #2
    Hallo,

    in der Standardeinstellung prüft ADO über ein erneutes Einlesen des Datensatzes nach, ob der Vorgang erfolgreich war - wobei allerdings alle Spalten in der WHERE-Einschränkung der SELECT-Anweisung verwendet werden. Falls nun ein Trigger einen Spaltenwert direkt in der Datenbank ändert, muss diese Kontroll-SELECT-Anweisung ins Leere gehen, d.h. liefert keinen Treffer zurück.

    Um dieses Problem zu lösen, muss die Recordset-Eigenschaft <b>'Resync Command'</b> so gesetzt werden, dass nur der Primärschlüssel der Tabelle als WHERE-Kriterium herangezogen wird (denn dieser Wert ändert sich nie):
    <pre>
    with ADODataSet1.Recordset do
    begin
    Properties['Resync Command'].Value := 'SELECT....';
    Resync(adAffectCurrent, adResyncAllValues);
    end;
    </pre>

    &gt;..Key column information is insufficient or incorrect. Too many rows were affected by update. ..

    Diese Fehlermeldung deutet allerdings darauf hin, dass die Tabelle <b>keinen Primärschlüssel</b> hat. Das ist zwar im SQL-Standard erlaubt - aber in der Praxis nicht üblich, ADO nimmt auf einen derartigen Extremfall keine Rücksicht. Die Tabelle muss einen Primärschlüssel bekommen.

    Bei einem Serverseitigen Cursor navigiert der SQL Server direkt über die Position des Datensatzes, aber bei einem clientseitigen Cursor muss der Zugriff über SQL erfolgen. Das ist jedoch nur dann erfolgreich, wenn jeder Datensatz logisch <b>eindeutig</b> in der Menge identifiziert werden kann. Und diesen Job übernimmt der Primärschlüssel - der einen logisch eindeutigen Wert für das Selektionskriterium erzwingt

    Comment


    • #3
      Hallo

      Die Tabelle hat einen Primärschlüssel (Spalte "c_style_id ").
      So wie ich das jetzt verstanden habe muss ich im Resync Query sicherstellen, dass nur die Splate des Primärschlüssels zum Vergleich herangezogen wird. Dies würde dann so aussehen: "SELECT c_style_id FROM t_style WHERE c_style_id = 1" wenn der zu ändernde Datensatz die ID 1 hat. Oder habe ich da etwas falsch verstanden?

      Dieses Query habe ich jetzt einmal ausprobiert und habe den selben Effekt bekommen. Das Problem ist ja eigentlich auch nicht, dass sich ein Wert der Tabelle ändert, sondern ein Wert in einer anderen Tabelle.

      Lotha

      Comment


      • #4
        Ich habe die Lösung gefunden.

        Problem: <BR>
        Das Problem war offenbar, dass im Trigger eine zusätzliche Spalte einer anderen Tabelle verändert wurde. ADO hatte nun das Gefühl, dass eine Spalte zuviel involviert sei.

        Lösung:<BR>
        Als erste Zeile im Trigger muss das Kommando "Set NOCOUNT ON" stehen. So erhält ADO vom SQL Server die Anzahl der geänderten Spalten nicht mehr und ist zufrieden. Die Anzahl der geänderten Datensätze kann immer noch mit "@@ROWCOUNT" abgefragt werden.

        Besten Dank für die Unterstützung --> Lotha

        Comment

        Working...
        X