パーティションIDを使用して特定のパーティションからデータを削除したいのですが。 SQL 2016の特定のパーティションからデータを切り捨てるクエリを取得しましたが、それより低いバージョンのクエリは見つかりませんでした。
以下のクエリを実行して、パーティションID 14および15のパーティションからデータのみを削除しました。
delete from partitiontable1 WITH (PARTITIONS (14 to 15))
Deleteステートメントは、パーティション自体をデータと共に削除しますか?
パーティションをそのままにして、特定のパーティションからデータを削除したい。たとえば、テーブルにパーティションを作成し、5つのパーティション(1、2、3、4、5)があり、2番目と3番目のパーティションからのみデータを削除したいとします。
この削除ステートメントは無効なSQL Server 2012構文であるため、エラーが発生するだけです。
パーティションとそれに関連付けられた境界を削除するには、MERGE
DDLを使用します。 DELETE
のようなDMLステートメントはパーティションを削除しません。
SQL 2014以前のバージョンでパーティションからすべての行を削除する最も効率的な方法は、SWITCH
を使用することです(SQL 2016では、特定のパーティションをTRUNCATE
で指定できます)。 SWITCHを使用するには、同じスキーマとインデックスを使用して、同様にパーティション分割されたステージングテーブルを作成します。次に、メタデータ操作としてテーブル間でデータを切り替え、次にステージングテーブルをTRUNCATE
できます。
ALTER TABLE dbo.YourTable
SWITCH PARTITION 1 TO dbo.YourTable_Staging PARTITION 1;
ALTER TABLE dbo.YourTable
SWITCH PARTITION 2 TO dbo.YourTable_Staging PARTITION 2;
ALTER TABLE dbo.YourTable
SWITCH PARTITION 3 TO dbo.YourTable_Staging PARTITION 3;
ALTER TABLE dbo.YourTable
SWITCH PARTITION 4 TO dbo.YourTable_Staging PARTITION 4;
ALTER TABLE dbo.YourTable
SWITCH PARTITION 5 TO dbo.YourTable_Staging PARTITION 5;
TRUNCATE TABLE dbo.YourTable_Staging;
この回答は Cathrine Wilhemsen からのものです。彼女が近くのイベントに出席している場合は、プレゼントを読んで見ることを強くお勧めします。コードは主に彼女から来ており、 Itzik Ben-Gan へのシャウトアウトと彼の関数GetNumsがあります。
要約すると、パーティションを新しいテーブルに切り替えて、テーブルを削除します。その後もパーティション番号は残ります。以下のコード(主にCathrineからのものですが、少し変更しました)をデモとして参照してください。
-- Drop objects if they already exist
IF EXISTS (SELECT * FROM sys.tables WHERE name = N'SalesSource')
DROP TABLE SalesSource;
IF EXISTS (SELECT * FROM sys.tables WHERE name = N'SalesTarget')
DROP TABLE SalesTarget;
IF EXISTS (SELECT * FROM sys.partition_schemes WHERE name = N'psSales')
DROP PARTITION SCHEME psSales;
IF EXISTS (SELECT * FROM sys.partition_functions WHERE name = N'pfSales')
DROP PARTITION FUNCTION pfSales;
-- Create the Partition Function
CREATE PARTITION FUNCTION pfSales (DATE)
AS RANGE RIGHT FOR VALUES
('2013-01-01', '2014-01-01', '2015-01-01');
-- Create the Partition Scheme
CREATE PARTITION SCHEME psSales
AS PARTITION pfSales
ALL TO ([Primary]);
-- Create the Partitioned Source Table (Heap) on the Partition Scheme
CREATE TABLE SalesSource (
SalesDate DATE,
Quantity INT
) ON psSales(SalesDate);
IF OBJECT_ID(N'dbo.GetNums', N'IF') IS NOT NULL DROP FUNCTION dbo.GetNums;
GO
CREATE FUNCTION dbo.GetNums(@low AS BIGINT, @high AS BIGINT) RETURNS TABLE
AS
RETURN
WITH
L0 AS (SELECT c FROM (SELECT 1 UNION ALL SELECT 1) AS D(c)),
L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
L4 AS (SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
L5 AS (SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
Nums AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rownum
FROM L5)
SELECT TOP(@high - @low + 1) @low + rownum - 1 AS n
FROM Nums
ORDER BY rownum;
GO
-- Insert test data
INSERT INTO SalesSource(SalesDate, Quantity)
SELECT DATEADD(DAY,dates.n-1,'2012-01-01') AS SalesDate, qty.n AS Quantity
FROM GetNums(1,1000) dates
CROSS JOIN GetNums(1,1000) AS qty;
-- Create the Non-Partitioned Target Table (Heap) on the [PRIMARY] filegroup
CREATE TABLE SalesTarget (
SalesDate DATE,
Quantity INT
) ON [PRIMARY];
-- Verify row count before switch
SELECT
pstats.partition_number AS PartitionNumber
,pstats.row_count AS PartitionRowCount
FROM sys.dm_db_partition_stats AS pstats
WHERE pstats.object_id = OBJECT_ID('Salessource')
ORDER BY PartitionNumber; -- 366000 rows in Partition 1, 365000 rows in Partition 2 and 269000 in 3 and 0 in 4
SELECT COUNT(*) FROM SalesTarget; -- 0 rows
-- Turn on statistics
SET STATISTICS TIME ON;
-- Is it really that fast...?
ALTER TABLE SalesSource SWITCH PARTITION 1 TO SalesTarget;
-- YEP! SUPER FAST!
-- Turn off statistics
SET STATISTICS TIME OFF;
-- Verify row count after switch
SELECT
pstats.partition_number AS PartitionNumber
,pstats.row_count AS PartitionRowCount
FROM sys.dm_db_partition_stats AS pstats
WHERE pstats.object_id = OBJECT_ID('SalesSource')
ORDER BY PartitionNumber; -- 0 rows in Partition 1, 365000 rows in Partition 2 and 269000 in 3 and 0 in 4
SELECT COUNT(*) FROM SalesTarget; -- 366000 rows