【发布时间】:2013-10-18 21:00:46
【问题描述】:
我已经成功解决了关于按值交换行的问题here 仍然有效。
但是通过使用此功能,我发现在拖放行方面缺乏一些功能。
我尝试获得解决方案here,其中讨论出错并且提供的解决方案不充分,因为他们需要额外的专栏。
这是众所周知的表:
DROP TABLE IF EXISTS kalksad1;
CREATE TABLE kalksad1(
kalk_id int PRIMARY KEY,
brkalk integer,
brred integer,
description text);
INSERT INTO kalksad1 VALUES
(12, 2, 5, 'text index 12 doc 2 row 5'),
(26, 2, 1, 'text index 26 doc 2 row 1'),
(30, 2, 2, 'text index 30 doc 2 row 2'),
(32, 4, 1, 'text index 32 doc 4 row 1'),
(36, 1, 1, 'text index 36 doc 1 row 1'),
(37, 1, 2, 'text index 37 doc 1 row 2'),
(38, 5, 1, 'text index 38 doc 5 row 1'),
(39, 5, 2, 'text index 39 doc 5 row 2'),
(42, 2, 3, 'text index 42 doc 2 row 3'),
(43, 2, 4, 'text index 43 doc 2 row 4'),
(46, 3, 1, 'text index 46 doc 3 row 1'),
(47, 3, 2, 'text index 47 doc 3 row 2');
操作对象是在相同的“brkalk”(doc) 下重新排序“brred”(row) 列的值。
设“brkalk”为 2。
现在我想根据拖放需求进行重新排序/交换,其中仅交换一行看起来不自然。我已将数据网格绑定到 kalksad1 表,因此我将描述在我的数据网格中填充查询“... ORDERED by brred”的情况。
如果我可以用这样的词来解释查询...
示例 1:
在 doc 2 下,我将拖动第 4 行并将其放到第 2 行的位置。
为此需要以下步骤:
1) 记住第 4 行的数据。
2) 在第 3 行中,将“brred”的值从 3 替换为 4。
3) 在第 2 行中,将“brred”的值从 2 替换为 3。
4)在步骤1的记忆数据中)将“brred”的值从4更改为2。
示例 2:
在 doc 2 下,我将拖动第 1 行并将其放到位置 3。
可以这样:
1) 记住第 1 行的数据。
2) 在第 2 行中,将“brred”的值从 2 替换为 1。
3) 在第 3 行中,将“brred”的值从 3 替换为 2。
4) 在步骤 1 的记忆数据中。将“brred”的值从 1 更改为 3。
这可能来自带有交换和 SO 问题的优雅解决方案 like this、this 和 this。我根据自己的想法做例子,但如果有更好的,就不应该那样做。
如果有人可以以类似于用户 Roman Pekar 的swapping 的方式编写所描述的查询,请。
EDIT: Solution based on Example1 from Tometzky
Imports Npgsql
Public Class Form1
Dim dServer As String = "127.0.0.1"
Dim dPort As String = "5432"
Dim dUser As String = "postgres"
Dim dPass As String = yourpass
Dim ddatabase As String = yourdatabase
Private dragrect As Rectangle
Private dragindex, dropindex As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim conn As New NpgsqlConnection(String.Format( _
"Server={0};Port={1};User Id={2};Password={3};Database={4};", _
dServer, dPort, dUser, dPass, ddatabase))
conn.Open()
Using t As NpgsqlTransaction = conn.BeginTransaction()
Using cmd As New NpgsqlCommand( _
"DROP TABLE IF EXISTS kalksad1;", conn)
cmd.ExecuteNonQuery()
End Using
Using cmd As New NpgsqlCommand( _
"CREATE TABLE kalksad1(" & _
"kalk_id int PRIMARY KEY, " & _
"brkalk integer, " & _
"brred integer, " & _
"description text);", conn)
cmd.ExecuteScalar()
End Using
Using cmd As New NpgsqlCommand( _
"INSERT INTO kalksad1 VALUES" & _
"(12, 2, 5, 'text index 12 doc 2 row 5'), " & _
"(26, 2, 1, 'text index 26 doc 2 row 1'), " & _
"(30, 2, 2, 'text index 30 doc 2 row 2'), " & _
"(32, 4, 1, 'text index 32 doc 4 row 1'), " & _
"(36, 1, 1, 'text index 36 doc 1 row 1'), " & _
"(37, 1, 2, 'text index 37 doc 1 row 2'), " & _
"(38, 5, 1, 'text index 38 doc 5 row 1'), " & _
"(39, 5, 2, 'text index 39 doc 5 row 2'), " & _
"(42, 2, 3, 'text index 42 doc 2 row 3'), " & _
"(43, 2, 4, 'text index 43 doc 2 row 4'), " & _
"(46, 3, 1, 'text index 46 doc 3 row 1'), " & _
"(47, 3, 2, 'text index 47 doc 3 row 2');", conn)
cmd.ExecuteNonQuery()
End Using
t.Commit()
End Using
With DataGridView1
.AllowDrop = True
.MultiSelect = False
.Dock = DockStyle.Fill
.SelectionMode = DataGridViewSelectionMode.FullRowSelect
.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
.Columns.Add("col1", "ID")
.Columns.Add("col2", "Doc")
.Columns.Add("col3", "Row")
.Columns.Add("col4", "Description")
End With
FillData(0)
End Sub
Private Sub FillData(ByVal dropindex As Integer)
DataGridView1.Rows.Clear()
Try
Using mCon As New NpgsqlConnection(String.Format( _
"Server={0};Port={1};User Id={2};Password={3};Database={4};", _
dServer, dPort, dUser, dPass, ddatabase))
mCon.Open()
Using mCmd = New NpgsqlCommand( _
"SELECT kalk_id, brkalk, brred, description " & _
"FROM kalksad1 " & _
"WHERE brkalk='2' ORDER BY brred", mCon)
Using reader As NpgsqlDataReader = mCmd.ExecuteReader()
While (reader.Read())
DataGridView1.Rows.Add(New String() _
{CStr(reader("kalk_id")), _
CStr(reader("brkalk")), _
CStr(reader("brred")), _
CStr(reader("description"))})
End While
End Using
End Using
End Using
Catch ex As Exception
Debug.Print(ex.Message)
End Try
''selecting a row
If dropindex < 0 Then dropindex = 0
With DataGridView1
.Rows(dropindex).Selected = True
.CurrentCell = .Item(0, dropindex)
End With
End Sub
#Region "dragdrop"
Private Sub DataGridView1_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DataGridView1.DragDrop
Dim p As Point = Me.PointToClient(New Point(e.X, e.Y))
dropindex = DataGridView1.HitTest(p.X, p.Y).RowIndex
If (e.Effect = DragDropEffects.Move) Then
Dim dragRow As DataGridViewRow = CType(e.Data.GetData(GetType(DataGridViewRow)), DataGridViewRow)
Dim _from As Integer = dragindex + 1 ''grid is zero based, document is 1 based
Dim _to As Integer = dropindex + 1
Dim updown As String = ""
If _from < _to Then ''correction for up
_to = _to + 1
updown = "!"
End If
'' PROCEDURE HERE -----------------------------------------------------------------
Dim affected As Integer = 0
Try
Using conn As New NpgsqlConnection(String.Format( _
"Server={0};Port={1};User Id={2};Password={3};Database={4};", _
dServer, dPort, dUser, dPass, ddatabase))
conn.Open()
Using t As NpgsqlTransaction = conn.BeginTransaction()
Using cmd As New NpgsqlCommand( _
"UPDATE kalksad1 SET brred=_brred " & _
"FROM (" & _
" SELECT " & _
" row_number() OVER (" & _
" ORDER BY brred<" & _to.ToString & " DESC, brred" & updown & "=" & _from.ToString & " DESC, brred>=" & _to.ToString & " DESC, brred" & _
" ) AS _brred," & _
" kalk_id AS _kalk_id " & _
"FROM kalksad1 " & _
"WHERE brkalk=2 " & _
"ORDER BY _kalk_id" & _
") AS _ " & _
"WHERE kalk_id=_kalk_id AND brred!=_brred;", conn)
affected = CInt(cmd.ExecuteNonQuery())
End Using
If affected > 0 Then t.Commit()
End Using
End Using
Catch ex As Exception
Debug.Print(ex.Message)
End Try
''---------------------------------------------------------------------------------
FillData(dropindex) ''clear, fill and select dropped row
End If
End Sub
Private Sub DataGridView1_DragOver(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DataGridView1.DragOver
e.Effect = DragDropEffects.Move
End Sub
Private Sub DataGridView1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DataGridView1.MouseDown
dragindex = DataGridView1.HitTest(e.X, e.Y).RowIndex
If dragindex > -1 Then
Dim dragSize As Size = SystemInformation.DragSize
dragrect = New Rectangle(New Point(CInt(e.X - (dragSize.Width / 2)), CInt(e.Y - (dragSize.Height / 2))), dragSize)
Else
dragrect = Rectangle.Empty
End If
End Sub
Private Sub DataGridView1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DataGridView1.MouseMove
If (e.Button And MouseButtons.Left) = MouseButtons.Left Then
If (dragrect <> Rectangle.Empty AndAlso Not dragrect.Contains(e.X, e.Y)) Then
Me.DoDragDrop(DataGridView1.Rows(dragindex), DragDropEffects.Move)
End If
End If
End Sub
#End Region
End Class
【问题讨论】:
-
那么,基本上你想旋转列
brred的值对于一定范围的行? -
我不知道“旋转”。基本上我想 TAKE,MAKE PLACE 然后插入到这个地方,我不知道解释更准确......是的,所有操作都应该只针对 brred 的值。
-
是的,在 _from 和 _to 之间的位置值应该重新编号。如果您可以使用 NET 和 Npgsql,这里是可行的示例。它适用于向下拖动。
-
好吧,您可以将预期结果添加到您的问题中。我无法阅读您的脚本语言,而且看起来相当冗长和程序化。如果您真的想旋转,我认为我的翻转旗触发器(在您的第二个链接中)可以适应您的需求。
-
嗯,它部分是某种旋转加上一点点。这个例子对我来说有点复杂,因为我从不使用触发器和函数。但是这个可以适应在两个方向上正常工作。在最坏的情况下,我可以制作条件代码...感谢您对 PostgreSQL 的帮助!
标签: postgresql