web-dev-qa-db-ja.com

外部キーによって参照されるテーブルの分割

テーブルが1つあります。

CREATE TABLE [dbo].[entry]
(
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [EntryDate] [datetime] NOT NULL,
    [createddate] [datetime] NOT NULL,

    CONSTRAINT [PK_Entry_ID] PRIMARY KEY CLUSTERED 
    (
        [ID] ASC
    )
    WITH
    (
        PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
        ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80
    ) ON [PRIMARY]
) ON [PRIMARY];

...主キーは別のテーブルによって参照されます。このテーブルを分割するために、私はすでに次の手順を実行しました:

 CREATE PARTITION FUNCTION EntryFunc (DATE) 
   AS RANGE LEFT
   FOR VALUES ('2011-01-01')


  CREATE PARTITION SCHEME EntryScheme
    AS PARTITION EntryFunc
    TO ([FileGroup2], [PRIMARY])

上記の2つの手順は正常に完了しましたが、テーブルをパーティション分割しているときに、他のテーブルによって参照されているため、主キーのクラスター化インデックスを削除できません。私の動機は、作成された日付に従ってテーブルエントリを分割することです。

6
Rajni Patel

BOLから( http://technet.Microsoft.com/en-us/library/ms191160(v = sql.105).aspx

ソーステーブルとターゲットテーブルには、同じFOREIGN KEY制約が必要です。ターゲット表にFOREIGN KEY制約がある場合、ソース表は対応する列で定義された同じ外部キーを持つ必要があり、これらの外部キーはターゲット表と同じ主キーを参照する必要があります。ターゲットテーブルの対応する外部キーもis_not_trustedとマークされていない限り、ソーステーブルの外部キーはis_not_trusted(sys.foreign_keysカタログビューで表示可能)とマークできません。

したがって、外部キーによって参照されるテーブルをパーティション分割する場合、両方のテーブルに同じFKが必要です。

また、高速パーティショニングについては、以下のルールが適用されます。

fkは使用できません

ソーステーブルに主キーがある場合、主キー/外部キーは定義されません。ソース表とソース表が主キーを保持しているターゲット表の間には、アクティブな主キー/外部キーの関係はありません。

ターゲットテーブルに外部キーがある場合、主キー/外部キーは定義されません。ターゲット表が外部キーを保持しているソース表とターゲット表の間にアクティブな主キー/外部キーの関係があってはなりません。

別のテーブルの外部キーはソーステーブルを参照できません。ソーステーブルを別のテーブルの外部キーで参照することはできません。

したがって、制約を削除し、テーブルをパーティション分割して、コストレインを再作成する必要があります。トランザクションとして行う方が良いため、成功するとコミットしたり失敗したりするとロールバックできます。

ステップバイステップチュートリアルは、次の場所にあります。 http://www.mssqltips.com/sqlservertip/2888/how-to-partition-an-existing-sql-server-table/ And

http://www.confio.com/logicalread/sql-server-primary-key-vs-clustered-index,-part-3/#.Ui1lNGIpDFo

5
Kin Shah

必要に応じてパーティション分割された新しいテーブルを作成し、既存のテーブルに新しいパーティション分割スキームを適用するのではなく、古いテーブルからテーブルにデータをコピーします。

データがコピーされたら、古いテーブルへのリレーションを削除してドロップし、新しい名前を変更して古いテーブルの代わりにすべてのリレーションを再作成します。安全のためにトランザクション内でこれを実行してください。

CREATE PARTITION FUNCTION EntryFunc (DATE) 
   AS RANGE LEFT
   FOR VALUES ('2011-01-01')

CREATE PARTITION SCHEME EntryScheme 
AS PARTITION EntryFunc
TO ([FileGroup2], [PRIMARY])

CREATE TABLE [dbo].[tmp_entry]
(
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[EntryDate] [datetime] NOT NULL,
[createddate] [datetime] NOT NULL
) ON EntryScheme([EntryDate]);

SET IDENTITY_INSERT dbo.[tmp_entry] ON
IF EXISTS(SELECT * FROM dbo.[Entry])
    EXEC('INSERT INTO dbo.[tmp_entry] (ID, EntryDate, CreatedDate, /* ... */)
        SELECT ID, EntryDate, CreatedDate, /* ... */ 
        FROM dbo.[Entry] WITH (HOLDLOCK TABLOCKX)')
SET IDENTITY_INSERT dbo.[tmp_entry] OFF

IF NOT ((SELECT COUNT(*) FROM [Entry]) = (SELECT COUNT(*) FROM [tmp_entry]))
BEGIN
    PRINT 'Partition [Entry] - ABORT - Move Failed'     
END
ELSE
BEGIN
    /* DROP ALL FK CONSTRAINTS REFERENCING [Entry] */

    DROP TABLE dbo.[Entry]

    EXECUTE sp_rename N'dbo.tmp_entry', N'Entry', 'OBJECT' 

    ALTER TABLE dbo.[Entry] ADD CONSTRAINT Entry_PK PRIMARY KEY CLUSTERED  ( ID ) 
    ON [PRIMARY] /* don't add your pk to the partition scheme or it will have to include your partition key */

    /* RECREATE ALL FK CONSTRAINTS REFERENCING [Entry] */
    PRINT 'Partition [Entry] - COMPLETE'    
END
3
SMS