3

リモートAPIにクエリを実行して多数の検索を実行するアプリケーションがあります。結果は私のデータ層(SQL Server)に取り込まれ、そこでユーザーがさらに対話したいかどうかを確認します。ユーザーがそのアイテムの操作を開始すると、それがシステム内にとどまることが不可欠ですが、残りの結果はまったく役に立たず、スペースを占有するだけです。

別のテーブルによって参照されていない行を削除するためにsprocを実行するタスクを作成することを考えていました。それを行う方法はありますか?

別の言い方をすると、次のようになります。参照整合性の違反が原因でエラーが発生する行をスキップするdeleteステートメントを実行する方法はありますか?

編集:@Kosからの新しい情報に感謝します...私が検討している代替パスは、テーブルにビット列を追加し、行が使用されて、タスクで行を削除するだけでfalseとマークされた場合にtrueとマークすることです。

わかりやすくするために、ここに状況の概要を示します。これらの構文は完全ではないかもしれませんが、うまくいけば、次のようなアイデアが得られます。

-- Where all the results get pulled down and held (The table I want to clean up every 2 hours or so)
CREATE TABLE [reservations].[DumpTable](
    [utypeID] [bigint] IDENTITY(1,1) NOT NULL
    -- Other columns
    CONSTRAINT [PK_UnitTypesFound] PRIMARY KEY CLUSTERED 
    (
        [utypeID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]


-- This is one of many other tables that might reference the dump table
CREATE TABLE [reservations].[OtherTables](
    [memberID]  INT NOT NULL,
    [utypeID]   BIGINT NOT NULL -- Need to Know if the dumptable is referenced here
    CONSTRAINT [PK_MemberUnitTypes] PRIMARY KEY CLUSTERED
    (
        [memberID],
        [utypeID]
    ) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,     ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

ALTER TABLE [reservations].[OtherTables]  WITH CHECK ADD  CONSTRAINT [FK_OtherTable_DumpTable] FOREIGN KEY([utypeID])
    REFERENCES [reservations].[DumpTable] ([utypeID])

ALTER TABLE [reservations].[OtherTables] CHECK CONSTRAINT [FK_OtherTable_DumpTable]
4

5 に答える 5

5

私は今日同じ問題に遭遇し、ここに行き着きました。最終的に、私はローレンスがIMOを探していたものに近い別のアプローチを思いつきましたが、おそらくはるかに遅いので、私自身の状況では問題ではありません。

したがって、基本的にはカーソルを使用して行を1つずつ削除し、deleteステートメントをtry / catchブロックに入れて、制約エラーが発生した場合にループを再開します。

DECLARE @idc as int
DECLARE Contact_Cursor CURSOR FOR
SELECT ID 
FROM ContactInfo;
OPEN Contact_Cursor;
FETCH NEXT FROM Contact_Cursor INTO @idc 
WHILE @@FETCH_STATUS = 0
  BEGIN
    begin try
      delete from ContactInfo where id = @idc;
      FETCH NEXT FROM Contact_Cursor INTO @idc 
    end try
    begin catch
      FETCH NEXT FROM Contact_Cursor INTO @idc 
    end catch
   END;
CLOSE Contact_Cursor;
DEALLOCATE Contact_Cursor;
GO
于 2014-10-06T14:54:33.877 に答える
4

where句の代わりにjoinを使用して、このクエリを使用してクエリを高速化することもできます。

DELETE FROM DATA_TABLE 
FROM         DATA_TABLE LEFT OUTER JOIN
                      OTHERON DATA_TABLE.OTHER_TABLE_ID= OTHER.ID 
WHERE     (OTHER.ID IS NULL) and DATA_TABLE.SOME_TIMESTAMP < threshold_time
于 2012-10-03T06:23:24.427 に答える
1

@KosによるOPのコメントで推奨されたものと同様の解決策を採用することになりました。このテーブルの性質上、ユーザーが操作した場合に別のテーブルを参照する外部キーが少なくとも1つ必要であることに気付いたため、自然に発生しました。BIT列と同様に、次のようなステートメントを実行しているだけです。

DELETE FROM [table] WHERE ISNULL([colForeignKey], 0) = 0

他の人が訪れる場合は、@ Maryamからの回答を確認することをお勧めします。このページにアクセスするほとんどの人は、それが最善の解決策になると思います(少なくとも、この投稿の時点までは諦めています)。

助けてくれてありがとう

于 2012-10-03T23:42:12.197 に答える
1

あなたの質問は詳細については少しまばらですが、テーブルが次のようになっていると仮定します。

DATA_TABLE
    OTHER_TABLE_ID    INTEGER
    SOME_TIMESTAMP    DATETIME

OTHER_TABLE
    ID                INTEGER

次に、次のような基本的な削除を行います。

DELETE FROM DATA_TABLE dt WHERE dt.SOME_TIMESTAMP < threshold_time
  AND NOT EXISTS (SELECT 1 FROM OTHER TABLE WHERE ID = dt.OTHER_TABLE_ID;

トリックを行う必要があります。DATA_TABLEの特定の行を操作することを決定するために、ユーザーにある程度の時間を与える必要があると想定しています。

更新:OTHER_TABLEが特定のテーブルではないが、いくつかのテーブルのいずれかである可能性がある場合、最善の策は、行がデータベースの「どこか」で参照されていることを示すDATA_TABLEのフラグである可能性があります。このアプローチの欠点は、後で参照がなくなる可能性がある場合、フラグを維持するのが難しくなることです。

于 2012-10-03T04:36:33.633 に答える
1

このリンクを確認してください。これは、データベース内のすべての外部キー関係を取得するのに役立ちます。そこに与えられたスクリプトには、必要なテーブルのみをフィルタリングするためのプロビジョニングがあります。
リストを取得したら、それを一時テーブルにダンプできます。テーブルには、テーブル名と、それらの間にFK関係を持つ列名が含まれます。次に、このテーブルの各レコードをループし、動的クエリを使用して(テーブルと列の名前が行に存在するため)、FK関係にあるダンプテーブルのレコードを見つけて、別の一時テーブルにダンプする必要があります。 。最後にNOT EXIST、この一時テーブルで実行するすべてのレコードをダンプテーブルから削除します。
試してみます。それが役に立てば幸い!!

于 2012-10-03T05:16:03.953 に答える