将 SYSTEM_TIME 列从 DATETIME2(7) 缩小到 DATETIME2(3) 的脚本
Script to downsize SYSTEM_TIME column from DATETIME2(7) to DATETIME2(3)
对于数据库中的所有临时表,我寻找一个生成 T-SQL 的脚本,以将它们的 SYSTEM_TIME 列从 DATETIME2(7) 缩小到 DATETIME2(3)。
我的理由: 当表通过 ODBC 连接链接时,我希望能够从 MS Access 数据库中更新这些表。通过 ODBC 驱动程序链接时,Access 不支持 DATETIME2(7)
更新(字段太大)。反之,SQL Server Native Client 驱动可以(据说我没试过);但它不支持 Active Directory - 集成 连接。此外,我的应用程序不需要这些字段的额外精度。
生成的代码如下所示。只是好奇是否有人可能有这样的脚本?
CREATE TABLE [dbo].[Tasks] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Task] NVARCHAR(50) NOT NULL,
[ValidFrom] DATETIME2(7) GENERATED ALWAYS AS ROW START HIDDEN NOT NULL,
[ValidTo] DATETIME2 (7) GENERATED ALWAYS AS ROW END HIDDEN NOT NULL,
[Who] NVARCHAR (128) CONSTRAINT [DF_dbo_Tasks_Who] DEFAULT (SUSER_SNAME()) NOT NULL,
CONSTRAINT [PK_dbo_Tasks] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [UQ_Tasks_Task] UNIQUE NONCLUSTERED ([Task] ASC),
PERIOD FOR SYSTEM_TIME ([ValidFrom], [ValidTo])
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE=[dbo].[History_Tasks], DATA_CONSISTENCY_CHECK=ON));
GO
INSERT INTO dbo.Tasks (Task)
VALUES (N'Task 1'), (N'Task 2'), (N'Task 3'), (N'Task 4'), (N'Task 5');
GO
UPDATE dbo.Tasks SET Task = N'Task 1.1' WHERE Id = 1;
DELETE FROM dbo.Tasks WHERE Id = 3;
INSERT INTO dbo.Tasks (Task) VALUES (N'Task 6');
GO
SELECT * FROM dbo.Tasks
SELECT * FROM dbo.History_Tasks
GO
---------------------------------------------------------------------------------------------------
ALTER TABLE dbo.Tasks SET (SYSTEM_VERSIONING = OFF);
ALTER TABLE dbo.Tasks DROP PERIOD FOR SYSTEM_TIME;
GO
ALTER TABLE dbo.Tasks ALTER COLUMN ValidFrom DATETIME2(3) NOT NULL;
ALTER TABLE dbo.Tasks ALTER COLUMN ValidTo DATETIME2(3) NOT NULL;
DROP INDEX ix_History_Tasks ON dbo.History_Tasks;
ALTER TABLE dbo.History_Tasks ALTER COLUMN ValidFrom DATETIME2(3) NOT NULL;
ALTER TABLE dbo.History_Tasks ALTER COLUMN ValidTo DATETIME2(3) NOT NULL;
ALTER TABLE dbo.Tasks ADD PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo);
ALTER TABLE dbo.Tasks SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE=dbo.History_Tasks));
CREATE CLUSTERED INDEX ix_History_Tasks ON dbo.History_Tasks(ValidTo ASC, ValidFrom ASC);
GO
---------------------------------------------------------------------------------------------------
-- ... Next table ...
您可以添加一个新列,将其设置为旧列的值,删除旧列,然后将新列重命名为旧名称。
以下将为您生成脚本,然后您可以执行该脚本。请注意,我面前没有 SQL 服务器,因此您需要仔细检查我的引号转义。
SELECT 'ALTER TABLE ' + t.table_name + ' ADD new_col DateTime2(3); UPDATE TABLE ' +
t.table_name + ' SET new_col = ' + c.column_name + '; ALTER TABLE ' +
t.table_name + ' DROP COLUMN ' + c.column_name + '; EXEC sp_rename ''' +
t.table_name + '.new_col'', ''' + c.column_name + ''' + , '''COLUMN''' + '; '
FROM information_schema.tables t
INNER JOIN information_schema.columns c ON t.object_id=c.object_id
WHERE c. --pick out your temporal columns here by type or name
对于每个 table/column 组合,它会给你这样的东西:
ALTER TABLE myTable ADD new_col DateTime2(3);
UPDATE myTable SET new_col = oldColName;
ALTER TABLE myTable DROP COLUMN oldColName;
EXEC sp_rename 'myTable.new_col', 'oldColName', 'COLUMN';
以下代码可以解决问题:
WITH a AS (
SELECT
SCHEMA_NAME(t.schema_id) AS PrimarySchema
, t.name AS PrimaryTable
, OBJECT_SCHEMA_NAME(t.history_table_id) AS HistorySchema
, OBJECT_NAME(t.history_table_id) AS HistoryTable
, i.name AS HistoryIndexName
FROM sys.tables AS t
JOIN sys.indexes AS i ON t.history_table_id = i.object_id -- There should only be one index on each history table
WHERE t.temporal_type = 2 -- SYSTEM_VERSIONED_TEMPORAL_TABLE
), b AS (
SELECT a.PrimarySchema
, a.PrimaryTable
, CONCAT(a.PrimarySchema, N'.', a.PrimaryTable) AS PrimarySchemaTable
, a.HistorySchema
, a.HistoryTable
, CONCAT(a.HistorySchema, N'.', a.HistoryTable) AS HistorySchemaTable
, a.HistoryIndexName
FROM a
), c AS (
SELECT b.PrimarySchema, b.PrimaryTable
, CONCAT(N'ALTER TABLE ', b.PrimarySchemaTable , N' SET (SYSTEM_VERSIONING = OFF);') AS L1
, CONCAT(N'ALTER TABLE ', b.PrimarySchemaTable , N' DROP PERIOD FOR SYSTEM_TIME;') AS L2
, N'GO' AS L3
, CONCAT(N'ALTER TABLE ', b.PrimarySchemaTable , N' ALTER COLUMN ValidFrom DATETIME2(3) NOT NULL;') AS L4
, CONCAT(N'ALTER TABLE ', b.PrimarySchemaTable , N' ALTER COLUMN ValidTo DATETIME2(3) NOT NULL;') AS L5
, CONCAT(N'DROP INDEX ', b.HistoryIndexName, N' ON ', b.HistorySchemaTable , N';') AS L6
, CONCAT(N'ALTER TABLE ', b.HistorySchemaTable, N' ALTER COLUMN ValidFrom DATETIME2(3) NOT NULL;') AS L7
, CONCAT(N'ALTER TABLE ', b.HistorySchemaTable, N' ALTER COLUMN ValidTo DATETIME2(3) NOT NULL;') AS L8
, CONCAT(N'ALTER TABLE ', b.PrimarySchemaTable , N' ADD PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo);') AS L9
, CONCAT(N'ALTER TABLE ', b.PrimarySchemaTable , N' SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE=', b.HistorySchemaTable, N'));') AS L10
, CONCAT(N'CREATE CLUSTERED INDEX ', b.HistoryIndexName, N' ON ', b.HistorySchemaTable, N'(ValidTo ASC, ValidFrom ASC);') AS L11
, N'GO' AS L12
, N'-------------------------------------------------------------------------------------------------------------------------' AS L13
FROM b
)
SELECT CONCAT(c.L1, CHAR(10), c.L2, CHAR(10), c.L3, CHAR(10), c.L4, CHAR(10), c.L5, CHAR(10), c.L6, CHAR(10), c.L7, CHAR(10), c.L8, CHAR(10), c.L9, CHAR(10), c.L10, CHAR(10), c.L11, CHAR(10), c.L12, CHAR(10), c.L13, CHAR(10)) AS Statements
FROM c
ORDER BY c.PrimarySchema, c.PrimaryTable
对于数据库中的所有临时表,我寻找一个生成 T-SQL 的脚本,以将它们的 SYSTEM_TIME 列从 DATETIME2(7) 缩小到 DATETIME2(3)。
我的理由: 当表通过 ODBC 连接链接时,我希望能够从 MS Access 数据库中更新这些表。通过 ODBC 驱动程序链接时,Access 不支持 DATETIME2(7)
更新(字段太大)。反之,SQL Server Native Client 驱动可以(据说我没试过);但它不支持 Active Directory - 集成 连接。此外,我的应用程序不需要这些字段的额外精度。
生成的代码如下所示。只是好奇是否有人可能有这样的脚本?
CREATE TABLE [dbo].[Tasks] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Task] NVARCHAR(50) NOT NULL,
[ValidFrom] DATETIME2(7) GENERATED ALWAYS AS ROW START HIDDEN NOT NULL,
[ValidTo] DATETIME2 (7) GENERATED ALWAYS AS ROW END HIDDEN NOT NULL,
[Who] NVARCHAR (128) CONSTRAINT [DF_dbo_Tasks_Who] DEFAULT (SUSER_SNAME()) NOT NULL,
CONSTRAINT [PK_dbo_Tasks] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [UQ_Tasks_Task] UNIQUE NONCLUSTERED ([Task] ASC),
PERIOD FOR SYSTEM_TIME ([ValidFrom], [ValidTo])
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE=[dbo].[History_Tasks], DATA_CONSISTENCY_CHECK=ON));
GO
INSERT INTO dbo.Tasks (Task)
VALUES (N'Task 1'), (N'Task 2'), (N'Task 3'), (N'Task 4'), (N'Task 5');
GO
UPDATE dbo.Tasks SET Task = N'Task 1.1' WHERE Id = 1;
DELETE FROM dbo.Tasks WHERE Id = 3;
INSERT INTO dbo.Tasks (Task) VALUES (N'Task 6');
GO
SELECT * FROM dbo.Tasks
SELECT * FROM dbo.History_Tasks
GO
---------------------------------------------------------------------------------------------------
ALTER TABLE dbo.Tasks SET (SYSTEM_VERSIONING = OFF);
ALTER TABLE dbo.Tasks DROP PERIOD FOR SYSTEM_TIME;
GO
ALTER TABLE dbo.Tasks ALTER COLUMN ValidFrom DATETIME2(3) NOT NULL;
ALTER TABLE dbo.Tasks ALTER COLUMN ValidTo DATETIME2(3) NOT NULL;
DROP INDEX ix_History_Tasks ON dbo.History_Tasks;
ALTER TABLE dbo.History_Tasks ALTER COLUMN ValidFrom DATETIME2(3) NOT NULL;
ALTER TABLE dbo.History_Tasks ALTER COLUMN ValidTo DATETIME2(3) NOT NULL;
ALTER TABLE dbo.Tasks ADD PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo);
ALTER TABLE dbo.Tasks SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE=dbo.History_Tasks));
CREATE CLUSTERED INDEX ix_History_Tasks ON dbo.History_Tasks(ValidTo ASC, ValidFrom ASC);
GO
---------------------------------------------------------------------------------------------------
-- ... Next table ...
您可以添加一个新列,将其设置为旧列的值,删除旧列,然后将新列重命名为旧名称。
以下将为您生成脚本,然后您可以执行该脚本。请注意,我面前没有 SQL 服务器,因此您需要仔细检查我的引号转义。
SELECT 'ALTER TABLE ' + t.table_name + ' ADD new_col DateTime2(3); UPDATE TABLE ' +
t.table_name + ' SET new_col = ' + c.column_name + '; ALTER TABLE ' +
t.table_name + ' DROP COLUMN ' + c.column_name + '; EXEC sp_rename ''' +
t.table_name + '.new_col'', ''' + c.column_name + ''' + , '''COLUMN''' + '; '
FROM information_schema.tables t
INNER JOIN information_schema.columns c ON t.object_id=c.object_id
WHERE c. --pick out your temporal columns here by type or name
对于每个 table/column 组合,它会给你这样的东西:
ALTER TABLE myTable ADD new_col DateTime2(3);
UPDATE myTable SET new_col = oldColName;
ALTER TABLE myTable DROP COLUMN oldColName;
EXEC sp_rename 'myTable.new_col', 'oldColName', 'COLUMN';
以下代码可以解决问题:
WITH a AS (
SELECT
SCHEMA_NAME(t.schema_id) AS PrimarySchema
, t.name AS PrimaryTable
, OBJECT_SCHEMA_NAME(t.history_table_id) AS HistorySchema
, OBJECT_NAME(t.history_table_id) AS HistoryTable
, i.name AS HistoryIndexName
FROM sys.tables AS t
JOIN sys.indexes AS i ON t.history_table_id = i.object_id -- There should only be one index on each history table
WHERE t.temporal_type = 2 -- SYSTEM_VERSIONED_TEMPORAL_TABLE
), b AS (
SELECT a.PrimarySchema
, a.PrimaryTable
, CONCAT(a.PrimarySchema, N'.', a.PrimaryTable) AS PrimarySchemaTable
, a.HistorySchema
, a.HistoryTable
, CONCAT(a.HistorySchema, N'.', a.HistoryTable) AS HistorySchemaTable
, a.HistoryIndexName
FROM a
), c AS (
SELECT b.PrimarySchema, b.PrimaryTable
, CONCAT(N'ALTER TABLE ', b.PrimarySchemaTable , N' SET (SYSTEM_VERSIONING = OFF);') AS L1
, CONCAT(N'ALTER TABLE ', b.PrimarySchemaTable , N' DROP PERIOD FOR SYSTEM_TIME;') AS L2
, N'GO' AS L3
, CONCAT(N'ALTER TABLE ', b.PrimarySchemaTable , N' ALTER COLUMN ValidFrom DATETIME2(3) NOT NULL;') AS L4
, CONCAT(N'ALTER TABLE ', b.PrimarySchemaTable , N' ALTER COLUMN ValidTo DATETIME2(3) NOT NULL;') AS L5
, CONCAT(N'DROP INDEX ', b.HistoryIndexName, N' ON ', b.HistorySchemaTable , N';') AS L6
, CONCAT(N'ALTER TABLE ', b.HistorySchemaTable, N' ALTER COLUMN ValidFrom DATETIME2(3) NOT NULL;') AS L7
, CONCAT(N'ALTER TABLE ', b.HistorySchemaTable, N' ALTER COLUMN ValidTo DATETIME2(3) NOT NULL;') AS L8
, CONCAT(N'ALTER TABLE ', b.PrimarySchemaTable , N' ADD PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo);') AS L9
, CONCAT(N'ALTER TABLE ', b.PrimarySchemaTable , N' SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE=', b.HistorySchemaTable, N'));') AS L10
, CONCAT(N'CREATE CLUSTERED INDEX ', b.HistoryIndexName, N' ON ', b.HistorySchemaTable, N'(ValidTo ASC, ValidFrom ASC);') AS L11
, N'GO' AS L12
, N'-------------------------------------------------------------------------------------------------------------------------' AS L13
FROM b
)
SELECT CONCAT(c.L1, CHAR(10), c.L2, CHAR(10), c.L3, CHAR(10), c.L4, CHAR(10), c.L5, CHAR(10), c.L6, CHAR(10), c.L7, CHAR(10), c.L8, CHAR(10), c.L9, CHAR(10), c.L10, CHAR(10), c.L11, CHAR(10), c.L12, CHAR(10), c.L13, CHAR(10)) AS Statements
FROM c
ORDER BY c.PrimarySchema, c.PrimaryTable