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

时间:2011-02-03 02:48:21

标签: 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)设置了正确的顺序。原来。

我需要找出是否有更新的Sql语句,它允许我交换所选记录的Column_Order。与之前的记录相同。

希望这是有道理的。

4 个答案:

答案 0 :(得分:0)

我相信这会为你做到这一点......

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

答案 1 :(得分:0)

交换两个位置。使用最后一个AND :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中存在一个错误,它不会一次性设置所有4个:order参数的参数。除非已知DBMS优化特定DBMS的查询,否则将需要4个参数都具有相同的值。

答案 2 :(得分:0)

这是使用TADOCommand调用更新语句两次执行所需的Delphi代码。这是针对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;

答案 3 :(得分:0)

我可能错了,但似乎在这种情况下你不必只有一个声明解决方案。我也没有看到它暗示,因为你只是在谈论 UPDATE 声明,这并不意味着你不能有任何其他声明准备你的更新,是吗?但如果你确实考虑到了这一点,请原谅我,但我会继续前进。 :)

首先,我想知道您的Column_Order确实没有差距。因为如果没有间隙值从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)

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