ADOQuery、SQL语句和数据库中行的重新排序

ADOQuery、SQL语句和数据库中行的重新排序,sql,database,delphi,ado,Sql,Database,Delphi,Ado,我有一个名为p_Columns的数据库表。此表包含列 ID Column_Name Column_Type Column_Visible Column_Order 此数据表由显示dbgrid的应用程序填充和更新。 这个应用程序有一个按钮。单击时,它将获取所选行。把它往上移一行这是我需要帮助的地方 现在,我的初始SQL语句SELECT*FROM p_Columns Order by Column_Order asc设置了正确的顺序。起初 我需要找出是否有update Sql语句允许我交换所选记录

我有一个名为p_Columns的数据库表。此表包含列

ID
Column_Name
Column_Type
Column_Visible
Column_Order
此数据表由显示dbgrid的应用程序填充和更新。 这个应用程序有一个按钮。单击时,它将获取所选行。把它往上移一行这是我需要帮助的地方

现在,我的初始SQL语句SELECT*FROM p_Columns Order by Column_Order asc设置了正确的顺序。起初

我需要找出是否有update Sql语句允许我交换所选记录的列顺序。就在它之前


希望这是有意义的。

我相信这会对你有帮助

update P_Columns 
set Column_Order = ((select count(*) from P_Columns) + 1) - Column_Order 

交换两个位置。使用最后一个和:order>1,因此位置1不能与不存在的位置0交换

update datatable
set column_order = case 
                      when column_order = :order then column_order-1 
                      else column_order+1 
                   end
where column_order in (:order, :order-1)
  and :order > 1
CASE语句应该存在于大多数主要的DBMS中


注意:stock TADOQuery中有一个bug,它不会一次性设置参数all 4:order parameters。需要4个参数,所有参数都带有相同的值,除非已知DBMS优化了特定DBMS的查询。

以下是Delphi代码,它使用TADOCommand调用update语句两次来实现您想要的功能。这是针对MS SQL Server进行测试的。如果您不使用TADO*组件,您应该能够转换为您使用的任何数据库组件。ADODataSet1是网格中显示的数据

var
    CurrentID: Integer;
    CurrentOrder: Integer;
    PrevID: Integer;
    PrevOrder: Integer;
begin
    if ADODataSet1.RecNo > 1 then // Do not move the first row
    begin
        CurrentID := ADODataSet1['ID'];
        CurrentOrder := ADODataSet1['Column_Order'];

        ADODataSet1.Prior;
        PrevID := ADODataSet1['ID'];
        PrevOrder := ADODataSet1['Column_Order'];

        ADOCommand1.CommandText := 'update P_Columns set Column_Order = :Column_Order where ID = :ID';

        ADOCommand1.Parameters.ParamByName('Column_Order').Value := PrevOrder;
        ADOCommand1.Parameters.ParamByName('ID').Value := CurrentID;
        ADOCommand1.Execute;

        ADOCommand1.Parameters.ParamByName('Column_Order').Value := CurrentOrder;
        ADOCommand1.Parameters.ParamByName('ID').Value := PrevID;
        ADOCommand1.Execute;

        ADODataSet1.Requery([]);
    end;
end;

我可能错了,但在这种情况下,似乎你不必只有一种陈述式的解决方案。我也不认为这意味着什么,因为您只讨论了一个UPDATE语句,这并不意味着您不能让任何其他语句准备更新,是吗?但如果你真的想到了这一点,请原谅我,但我会继续前进

首先,我想知道你的专栏顺序是否确实没有空白。因为如果没有差距,且值从1开始,那么您可以仅通过此修改就可以使用cyberkiwi的解决方案,但所有信用都应归于此人:

declare @order int;
set @order = :order;

update P_Columns
set Column_Order =
  case 
    when Column_Order = @order then Column_Order - 1 
    else Column_Order + 1 
  end
where Column_Order in (@order, @order - 1) and @order > 1
也就是说,您需要声明@var,以便每个脚本只使用:order一次。你可能已经知道了。你在这儿

但是,如果该解决方案不能按原样应用,那么基本上,我认为,您只需要添加更多语句来预先计算由于交换而产生的其他订单值,然后进行更新

下面是它可能的样子:

declare @order int, @prev_order int;
set @order = :order;

/* here goes looking up for the other Column_Order */
select @prev_order = max(Column_Order)
from P_Columns
where Column_Order < @order;

/* and now update, which is basically the same,
   only adapted for use with @prevorder,
   and also we check if @prevorder has a value */
if @prevorder is not null
  update P_Columns
  set Column_Order =
    case Column_Order
      when @order then @prevorder
      else @order
    end
  where Column_Order in (@order, @prevorder)

如果您有任何问题,欢迎提问。

这是连接到哪个dbms的?我在这里做的是计算记录的计数,将其增加1,然后减去当前列的顺序…因此列的顺序列从1,2,3…5开始,然后转到5,4,3…1。您假设列的顺序a是数字,b在它的序列中没有间隙。这些假设是否到期?您可以使用行\号而不是列\顺序或等效项来修复代码,然后将您的逻辑应用于结果列。@1-有一条关于DBMS挂起的注释。这个问题表明没有差距,但OP可以澄清这是否属实。这个问题表明没有差距——它在哪里说的?数据类型也可以是整数或数字。谢谢你,这算是最好的了。我感谢大家的帖子。