PostgreSQL, Swap-Daten einer bestimmten Spalte in zwei Zeilen

Ich habe eine komplexe Funktion, um Daten aus derselben Namensspalte in verschiedenen Zeilen auszutauschen. Ich lese Daten aus der ersten Zeile, speichere sie in lokalen temporären Variablen, lese Daten aus der zweiten Zeile und speichere sie in der ersten Zeile, und speichere dann temporäre Variablen in der zweiten Zeile, was eine langsame und fehleranfällige Operation ist .

Daher dachte ich, dass das gleiche Ergebnis möglicherweise nur mit SQL erzielt werden kann.

Hier sind Beispieldaten:

CREATE TEMP TABLE tbl(
id        int PRIMARY KEY,
doc_num   integer, 
doc_text  text 
);

INSERT INTO tbl VALUES
  (1, 1, 'First column text1'),
  (2, 2, 'First column text2'),
  (4, 3, 'First column text3'),
  (7, 4, 'First column text4');

Piont soll nur 'doc_num' Spaltendaten in die gewünschte Richtung tauschen, die nach oben oder unten sein können, was ich mit separaten Funktionen mache.

Wenn ich eine einfache englische Abfrage schreiben kann, dann klingt das so:

Erste Abfrage:

SWAP DOC_NUM in row 2 with DOC_NUM in row 3 IF DOC_NUM in row 3 IS <= MAX(DOC_NUM);

Zweite Abfrage:

SWAP DOC_NUM in row 3 with DOC_NUM in row 2 IF DOC_NUM in row 2 IS >= MIN(DOC_NUM);

Können diese Abfragen mit PostgreSQL geschrieben werden und wie?

Hier ist echter Code (der hässlich ist) aus einem echten Programm, der "einen Job macht" und Verbesserungen benötigt.

 Private Sub DataGridView2_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DataGridView2.KeyDown

    'SWAP --------------------------------------
    If e.Control And e.KeyCode = Keys.Left Then
        Debug.Print("Swap left/down")

        Dim target_nrow As Integer
        Dim target_index As Integer
        Dim selected_nrow As Integer
        Dim selected_index As Integer
        Dim target_row As Integer = selected_row - 1
        Using conn As New NpgsqlConnection(String.Format("Server={0};Port={1};User Id={2};Password={3};Database={4};", dbServer, dbPort, dbUser, dbPass, mydatabase))
            conn.Open()
            Dim t As NpgsqlTransaction = conn.BeginTransaction()

            Using cmd As New NpgsqlCommand( _
                  "SELECT cur_id, doc_num, nrow " & _
                  "FROM " & mytable & " " & _
                  "WHERE doc_num='" & active_doc.ToString & "' AND nrow='" & selected_row.ToString & "'", conn)

                Using dr As NpgsqlDataReader = cmd.ExecuteReader()
                    While dr.Read()
                        selected_index = CInt(dr(0))
                        selected_nrow = CInt(dr(2))
                    End While
                End Using
            End Using

            Using cmd As New NpgsqlCommand( _
                  "SELECT cur_id, doc_num, nrow " & _
                  "FROM " & mytable & " " & _
                  "WHERE doc_num='" & active_doc.ToString & "' AND nrow='" & target_row.ToString & "'", conn)

                Using dr As NpgsqlDataReader = cmd.ExecuteReader()
                    While dr.Read()
                        target_index = CInt(dr(0))
                        target_nrow = CInt(dr(2))
                    End While
                End Using
            End Using

            Dim updated_t As Integer = 0
            Using cmd As New NpgsqlCommand( _
                  "UPDATE " & mytable & " SET " & _
                  "nrow=" & selected_nrow & " " & _
                  "WHERE cur_id=" & target_index.ToString, conn)

                updated_t = CInt(cmd.ExecuteNonQuery())
                cmd.Dispose()
            End Using

            Dim updated_s As Integer = 0
            Using cmd As New NpgsqlCommand( _
                  "UPDATE " & mytable & " SET " & _
                  "nrow=" & target_nrow & " " & _
                  "WHERE cur_id=" & selected_index.ToString, conn)

                updated_s = CInt(cmd.ExecuteNonQuery())
                cmd.Dispose()
            End Using

            If updated_s > 0 And updated_t > 0 Then
                t.Commit()
            Else
                t.Rollback()
            End If

            t.Dispose()
            conn.Close()
            conn.Dispose()
        End Using

        Refreshlist(active_doc)
    End If

    If e.Control And e.KeyCode = Keys.Right Then
        Debug.Print("Swap right/up")

        'similar code to swap up again

    End If

Die ganze Geschichte ist umstritten, wie man das kürzer, schneller und eleganter macht.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage