2011-02-03 4 views
0

P_Columnsというデータベース表があります。このテーブルには列が含まれますADOQuery、SQL文とデータベース内の行の並び替え

ID 
Column_Name 
Column_Type 
Column_Visible 
Column_Order 

このデータテーブルには、dbgridを表示するアプリケーションが作成され、更新されます。 このアプリケーションにはボタンがあります。クリックすると、選択した行が取り込まれます。 1行上に移動します(これは私が助けが必要なところです)。

私の最初のSQL文(SELECT * FROM P_Columns Order by Column_Order asc)は正しい順序を設定します。最初は

選択したレコードのColumn_Orderを交換できるようにする更新SQL文があるかどうかを調べる必要があります。その直前の記録と一致している。

希望はこれが理にかなっています。

+0

これはどのDBMSに接続していますか? – RichardTheKiwi

答えて

0

ここでは、TADOCommandを使用してupdate文を2回呼び出す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; 
+0

これは最高の結果を出しました。 私は誰も投稿を感謝します。 –

0

私はちょうど2つのポジションのスワップ

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

私がここでやっているのは、レコードのカウントを取って1ずつ増やしてから、現在のColumn_Orderを減算することです。そうすると、Column_Orderカラムは1,2,3 ... 5で始まり、5,4になります。 3 ... 1。 –

0

...これはあなたのためにそれを行うだろうと信じています。その位置1、位置0と交換することはできませんので、最後のAND :order > 1

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に存在する必要があります。

注:(在庫)TADOQueryには、パラメータall 4 :orderを一度に設定しないバグがあります。 DBMSが特定のDBMSに対してクエリを最適化することがわかっていない限り、4つのパラメータはすべて同じ値を保持する必要があります。

+0

あなたは 'column_order' a)が数値であると仮定していますが、b)そのシーケンスにはギャップがありません。これらの仮定は間違っていますか?あなたは 'ROW_NUMBER()OVER(ORDER BY column_order)'または同等のものを使ってコードを修正し、結果の列にロジックを適用することができます。 – onedaywhen

+0

@one - 保留中のDBMSについてのコメントがあります。問題はギャップがないことを示唆しているが、OPはそれが真実であるかどうかを明確にすることができる。 – RichardTheKiwi

+0

"問題は、ギャップがないことを示唆しています" - それはどこで言いますか?データ型は整数(または数値)である必要があります。 – onedaywhen

0

私は間違っているかもしれませんが、この場合は1つのステートメントのみの解決策を持つ必要はありません。 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) 

ご質問があれば、彼らは歓迎されています。

関連する問題