sync
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# SQL Server Management Studio Solution File, Format Version 18.00
|
||||
VisualStudioVersion = 15.0.28307.421
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{4F2E2C19-372F-40D8-9FA7-9D2138C6997A}") = "OCTPDBA-414 - proc to align indexes", "OCTPDBA-414 - proc to align indexes.ssmssqlproj", "{7E9B5A7A-BC32-4B75-8C24-E4D76990E6C4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Default|Default = Default|Default
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7E9B5A7A-BC32-4B75-8C24-E4D76990E6C4}.Default|Default.ActiveCfg = Default
|
||||
{CDCDFBE0-AA1A-4B35-BD71-6CA1EEB6DCCB}.Default|Default.ActiveCfg = Default
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {55F426D9-CD01-43F0-8B52-89D42AEDECF8}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0"?>
|
||||
<SqlWorkbenchSqlProject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="OCTPDBA-414 - proc to align indexes">
|
||||
<Items>
|
||||
<LogicalFolder Name="Connections" Type="2" Sorted="true">
|
||||
<Items>
|
||||
<ConnectionNode Name="(local):CENTRALINFRA\ua208700">
|
||||
<Created>2023-02-06T13:35:17.913386+01:00</Created>
|
||||
<Type>SQL</Type>
|
||||
<Server>(local)</Server>
|
||||
<UserName />
|
||||
<Authentication>Windows Authentication</Authentication>
|
||||
<InitialDB>master</InitialDB>
|
||||
<LoginTimeout>30</LoginTimeout>
|
||||
<ExecutionTimeout>0</ExecutionTimeout>
|
||||
<ConnectionProtocol>NotSpecified</ConnectionProtocol>
|
||||
<ApplicationName>Microsoft SQL Server Management Studio - Query</ApplicationName>
|
||||
</ConnectionNode>
|
||||
</Items>
|
||||
</LogicalFolder>
|
||||
<LogicalFolder Name="Queries" Type="0" Sorted="true">
|
||||
<Items>
|
||||
<FileNode Name="maintain entry indexes.sql">
|
||||
<AssociatedConnectionMoniker>8c91a03d-f9b4-46c0-a305-b5dcc79ff907:(local):True</AssociatedConnectionMoniker>
|
||||
<AssociatedConnSrvName>(local)</AssociatedConnSrvName>
|
||||
<AssociatedConnUserName />
|
||||
<FullPath>maintain entry indexes.sql</FullPath>
|
||||
</FileNode>
|
||||
<FileNode Name="proc.sql">
|
||||
<AssociatedConnectionMoniker>8c91a03d-f9b4-46c0-a305-b5dcc79ff907:(local):True</AssociatedConnectionMoniker>
|
||||
<AssociatedConnSrvName>(local)</AssociatedConnSrvName>
|
||||
<AssociatedConnUserName />
|
||||
<FullPath>proc.sql</FullPath>
|
||||
</FileNode>
|
||||
<FileNode Name="table.sql">
|
||||
<AssociatedConnectionMoniker>8c91a03d-f9b4-46c0-a305-b5dcc79ff907:(local):True</AssociatedConnectionMoniker>
|
||||
<AssociatedConnSrvName>(local)</AssociatedConnSrvName>
|
||||
<AssociatedConnUserName />
|
||||
<FullPath>table.sql</FullPath>
|
||||
</FileNode>
|
||||
</Items>
|
||||
</LogicalFolder>
|
||||
<LogicalFolder Name="Miscellaneous" Type="3" Sorted="true">
|
||||
<Items />
|
||||
</LogicalFolder>
|
||||
</Items>
|
||||
</SqlWorkbenchSqlProject>
|
||||
170
OCTPDBA-414 - proc to align indexes/generate inserts.sql
Normal file
170
OCTPDBA-414 - proc to align indexes/generate inserts.sql
Normal file
@@ -0,0 +1,170 @@
|
||||
USE Arizona;
|
||||
GO
|
||||
|
||||
DELETE FROM upd.IA_IndexesAlignementActions
|
||||
WHERE IA_schema_name = 'dbo.Criteria';
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
WITH ColInfo
|
||||
AS (SELECT TblName = o.name,
|
||||
SchemaTbl = s.name + '.' + o.name,
|
||||
IndexName = i.name,
|
||||
s.name AS schemaName,
|
||||
IsPrimaryKey = i.is_primary_key,
|
||||
IsUniqueConstraint = i.is_unique_constraint,
|
||||
IsUnique = i.is_unique,
|
||||
CASE
|
||||
WHEN i.type = 1 THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
END AS is_clustered,
|
||||
ColName = c.name,
|
||||
IsComputedCol = c.is_computed,
|
||||
IsIncludedCol = ic.is_included_column,
|
||||
ic.key_ordinal,
|
||||
FilterDefinition = i.filter_definition,
|
||||
i.object_id,
|
||||
i.ignore_dup_key,
|
||||
i.fill_factor,
|
||||
i.is_padded
|
||||
FROM sys.objects o
|
||||
JOIN sys.schemas s
|
||||
ON o.schema_id = s.schema_id
|
||||
JOIN sys.columns c
|
||||
ON o.object_id = c.object_id
|
||||
JOIN sys.indexes i
|
||||
ON c.object_id = i.object_id
|
||||
JOIN sys.index_columns ic
|
||||
ON i.index_id = ic.index_id
|
||||
AND o.object_id = ic.object_id
|
||||
AND c.column_id = ic.column_id
|
||||
WHERE o.name = 'criteria'
|
||||
AND s.name = 'dbo')
|
||||
SELECT DISTINCT
|
||||
'
|
||||
INSERT INTO arizona.upd.IA_IndexesAlignementActions
|
||||
(
|
||||
IA_executionDate,
|
||||
IA_schema_name,
|
||||
IA_table_name,
|
||||
IA_columns_name,
|
||||
IA_is_clustered,
|
||||
IA_is_unique,
|
||||
IA_included_columns,
|
||||
IA_is_to_be_deleted,
|
||||
IA_is_to_be_recreated,
|
||||
IA_expected_index_name,
|
||||
IA_foundIndexName,
|
||||
IA_wasIndexFound,
|
||||
IA_wasCreated,
|
||||
IA_wasRenamed,
|
||||
IA_wasDeleted,
|
||||
IA_wasRecreated,
|
||||
IA_includedColumnsMatch,
|
||||
IA_actualColumns,
|
||||
IA_actualIncludedColumns,
|
||||
IA_statusMsg,
|
||||
IA_index_options
|
||||
)
|
||||
SELECT
|
||||
NULL as IA_executionDate,
|
||||
''' + x.schemaName + ''' as IA_schema_name,
|
||||
''' + x.TblName + ''' as IA_table_name,
|
||||
''' + c.IndexColumns + ''' as IA_columns_name,
|
||||
0 as IA_is_clustered,
|
||||
' + CASE
|
||||
WHEN x.IsUnique = 0 THEN
|
||||
'0'
|
||||
ELSE
|
||||
'1'
|
||||
END + ' as IA_is_unique,
|
||||
' + CASE
|
||||
WHEN ci.IncludedColumns IS NOT NULL THEN
|
||||
'''' + ci.IncludedColumns + ''''
|
||||
ELSE
|
||||
'NULL'
|
||||
END + ' as IA_included_columns,
|
||||
0 as IA_is_to_be_deleted,
|
||||
0 as IA_is_to_be_recreated,
|
||||
''' + x.IndexName
|
||||
+ ''' as IA_expected_index_name,
|
||||
NULL as IA_foundIndexName,
|
||||
0 as IA_wasIndexFound,
|
||||
0 as IA_wasCreated,
|
||||
0 as IA_wasRenamed,
|
||||
0 as IA_wasDeleted,
|
||||
0 as IA_wasRecreated,
|
||||
NULL as IA_includedColumnsMatch,
|
||||
NULL as IA_actualColumns,
|
||||
NULL as IA_actualIncludedColumns,
|
||||
NULL as IA_statusMsg,
|
||||
''' + CASE
|
||||
WHEN INDEXPROPERTY(x.object_id, x.IndexName, 'IsStatistics') = 1 THEN
|
||||
'STATISTICS_NORECOMPUTE = ON, '
|
||||
ELSE
|
||||
'STATISTICS_NORECOMPUTE = OFF, '
|
||||
END + CASE
|
||||
WHEN x.ignore_dup_key = 1 THEN
|
||||
'IGNORE_DUP_KEY = ON, '
|
||||
ELSE
|
||||
'IGNORE_DUP_KEY = OFF, '
|
||||
END + CASE
|
||||
WHEN x.is_padded = 1 THEN
|
||||
'PAD_INDEX = ON,'
|
||||
ELSE
|
||||
''
|
||||
END + 'SORT_IN_TEMPDB = OFF, FILLFACTOR =' + CAST(x.fill_factor AS VARCHAR(3))
|
||||
+ ''' as IA_index_options
|
||||
WHERE NOT EXISTS(
|
||||
SELECT 1
|
||||
FROM arizona.upd.IA_IndexesAlignementActions s
|
||||
WHERE s.IA_executionDate IS NULL
|
||||
AND s.IA_schema_name = ''' + x.schemaName + '''
|
||||
AND s.IA_table_name = ''' + x.TblName + '''
|
||||
AND s.IA_columns_name = ''' + c.IndexColumns + '''
|
||||
' + CASE
|
||||
WHEN ci.IncludedColumns IS NOT NULL THEN
|
||||
'AND s.IA_included_columns = ''' + ci.IncludedColumns + ''' '
|
||||
ELSE
|
||||
''
|
||||
END + '
|
||||
)
|
||||
' AS cmd,
|
||||
x.IndexName,
|
||||
c.IndexColumns,
|
||||
ci.IncludedColumns
|
||||
FROM ColInfo x
|
||||
CROSS APPLY
|
||||
(
|
||||
SELECT IndexColumns = STUFF(sq.strXML, 1, 2, '')
|
||||
FROM
|
||||
(
|
||||
SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName
|
||||
AND x.schemaName = x2.schemaName
|
||||
AND x.IndexName = x2.IndexName
|
||||
AND x2.IsIncludedCol = 0
|
||||
ORDER BY x2.key_ordinal
|
||||
FOR XML PATH('')
|
||||
) sq(strXML)
|
||||
) c
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT IncludedColumns = STUFF(sq.strXML, 1, 2, '')
|
||||
FROM
|
||||
(
|
||||
SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName
|
||||
AND x.schemaName = x2.schemaName
|
||||
AND x.IndexName = x2.IndexName
|
||||
AND x2.IsIncludedCol = 1
|
||||
ORDER BY x2.key_ordinal
|
||||
FOR XML PATH('')
|
||||
) sq(strXML)
|
||||
) ci;
|
||||
|
||||
|
||||
ROLLBACK TRANSACTION;
|
||||
686
OCTPDBA-414 - proc to align indexes/maintain entry indexes.sql
Normal file
686
OCTPDBA-414 - proc to align indexes/maintain entry indexes.sql
Normal file
@@ -0,0 +1,686 @@
|
||||
/*=============================================================================
|
||||
|
||||
Maintain and align indexes on Arizona.dbo.entry
|
||||
|
||||
TODO:
|
||||
allow to skip INDEX DROP for unlisted indexes
|
||||
|
||||
Parameters
|
||||
----------------------
|
||||
Populate the var table @indexesToMaintains to drop / create and rename indexes to be aligned.
|
||||
You need to specify those fields:
|
||||
* schemaName, tableName: the schema and table name for which you want to maintain the indexes.
|
||||
This script was written with working against several tables in mind, but is not (yet) tested to handle this case.
|
||||
* columnsName: What columns are part of the index key, in the correct order
|
||||
As we have divergent indexes names, we must use the index columns as the key to find the indexes.
|
||||
* includedColumns_inp: if the index have included columns, list them here.
|
||||
When an index is found, the included columns list it also compared to determine if the index is aligned.
|
||||
* expectedIndexName_inp: The name the index should have. It will be used when creating missing indexes or renaming existing indexes
|
||||
The index name is optionnal if we specify in the table that the index must be dropped.
|
||||
* isToBeDeleted_inp: if true, indicate that the index should be dropped.
|
||||
* isToBeRecreated_inp: if true, will drop and re-create the index even if the structure matches.
|
||||
* isClustered_inp: if true and the index must be (re-)created, it will be created as a clustered index
|
||||
* isUnique_inp: if true and the index must be (re-)created, it will be created as a unique index
|
||||
|
||||
Note that:
|
||||
* Matching is always made from the columns of the index, never on the name of the index.
|
||||
The reason is that we might have difference in the name of the index between several servers.
|
||||
* If an index exists with the name A, but your list contains a similar index with the name B, index A will be renamed to B with sp_rename
|
||||
* For each table(s) referenced in @indexesToMaintains, if an index exists that is not listed in the variable table it will be considered to be
|
||||
dropped if @DoDropExistingIndexesNotReferenced is set to 1.
|
||||
* If you list a specific existing index to be dropped in @indexesToMaintains then the following fields are optionnal:
|
||||
expected index name
|
||||
flag isClustered
|
||||
flag isUnique
|
||||
|
||||
Context
|
||||
----------------------
|
||||
In any databases
|
||||
|
||||
Creation : 09.11.2022 / TSC
|
||||
Modifications:
|
||||
|
||||
=============================================================================*/
|
||||
USE [Arizona];
|
||||
GO
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
SET XACT_ABORT ON;
|
||||
SET NOCOUNT ON;
|
||||
|
||||
DECLARE @query VARCHAR(MAX); /* for dynamic sql */
|
||||
DECLARE @schemaName VARCHAR(100); /* used in cursor */
|
||||
DECLARE @tableName VARCHAR(100); /* used in cursor */
|
||||
|
||||
/*
|
||||
If set to true, the script will not apply the change.
|
||||
Generated statements are always printed on the message tab.
|
||||
*/
|
||||
DECLARE @DoOnlyOutputStatement BIT = 0;
|
||||
|
||||
/*
|
||||
If the script find local indexes that are not listed in the variable table, should it drop them or not ?
|
||||
An index whose definition is not aligned with the temp table or flagged "to be rebuilt" will always be dropped before creation.
|
||||
*/
|
||||
DECLARE @DoDropExistingIndexesNotReferenced BIT = 0;
|
||||
|
||||
DECLARE @indexesToMaintains TABLE(
|
||||
[Id] INT IDENTITY NOT NULL
|
||||
,[SchemaName] VARCHAR(100) NOT NULL /* the schema the table is part of */
|
||||
,[TableName] VARCHAR(100) NOT NULL /* On which table is the index, whithout the schema */
|
||||
,columnsName_inp VARCHAR(MAX) NOT NULL /* list all the columns of the index, in the correct orders */
|
||||
,isClustered_inp BIT NOT NULL DEFAULT 0 /* Is the indexe a clustered index ? */
|
||||
,isUnique_inp BIT NOT NULL DEFAULT 0 /* Is the index unique ? */
|
||||
,includedColumns_inp VARCHAR(MAX)NULL /* list all the included columns the index should have. only relevant for idx not to be dropped */
|
||||
,isToBeDeleted_inp BIT NOT NULL DEFAULT 0 /* must the script drop this index ? */
|
||||
,isToBeRecreated_inp BIT NOT NULL DEFAULT 0 /* must the script recreate this index ?
|
||||
If an existing index differs from the definition, it will be dropped and the correct one created.
|
||||
Use this only to force the re-creation even if the structure is identical */
|
||||
,expectedIndexName_inp VARCHAR(MAX) NULL /* the name the index should have, used to determine if a rename of the existing index should be done */
|
||||
,indexName VARCHAR(MAX) NULL /* computed by the script. The index name on this system, as indexes name can be different accross systems*/
|
||||
,isIndexFound_comp BIT NOT NULL DEFAULT 0 /* computed by the script. set to 1 if the index is present on the server */
|
||||
,isToBeCreated_comp BIT NULL DEFAULT 0 /* computed by the script. does this index will be created on the server ? */
|
||||
,isToBeRenamed_comp BIT NULL DEFAULT 0 /* computed by the script. does this index will be renamed ? */
|
||||
,isToBeDeleted_comp BIT NULL DEFAULT 0 /* computed by the script. does this index will be deleted ? */
|
||||
,isToBeRecreated_comp BIT NULL DEFAULT 0 /* computed by the script. does this index will be re-created ? */
|
||||
,internal_includedColumnsMatch BIT NULL /* computed ba the script. Are the expected and actual included columns identical ? */
|
||||
,internal_actualColumns VARCHAR(MAX) NULL /* the actual columns in the existing index */
|
||||
,internal_actualIncludedColumns VARCHAR(MAX) NULL /* the actual columns in the INCLUDE part of the index */
|
||||
,internal_statusMsg VARCHAR(MAX) /* Message, used for debug */
|
||||
);
|
||||
|
||||
/* Declare the expected structure of the indexes */
|
||||
INSERT INTO @indexesToMaintains ([columnsName_inp],
|
||||
[isToBeDeleted_inp],
|
||||
[isToBeRecreated_inp],
|
||||
[expectedIndexName_inp],
|
||||
[includedColumns_inp],
|
||||
[schemaName],
|
||||
[tableName],
|
||||
[isClustered_inp],
|
||||
[isUnique_inp])
|
||||
/* indexe(s) we do want */
|
||||
VALUES('Entry_id',0,0,'PK_Entry_id', NULL,'dbo','entry',0,0)
|
||||
,('ET_batch_run',0,0,'NCIX_Entry_COL_ET_batch_run',NULL,'dbo','entry',0,0)
|
||||
,('ET_accounting_period',0,0,'NCIX_Entry_COL_ET_accounting_period','Entry_ID','dbo','entry',0,0)
|
||||
,('ET_document_header',0,0,'NCIX_Entry_COL_ET_document_header','ET_debit_currency_amount, ET_credit_currency_amount','dbo','entry',0,0)
|
||||
,('ET_account, ET_document_header',0,0,'NCIX_Entry_COL_ET_account','Entry_ID','dbo','entry',0,0)
|
||||
,('ET_reconciliation_status, ET_account, ET_document_header',0,0,'NCIX_Entry_COL_ET_reconciliation_status','ET_debit_base_amount, ET_credit_base_amount, ET_reconciliation_base_amount','dbo','entry',0,0)
|
||||
,('ET_predefined_entry',0,0,'NCIX_Entry_COL_ET_predefined_entry',NULL,'dbo','entry',0,0)
|
||||
,('ET_entry_address',0,0,'NCIX_Entry_COL_ET_entry_address',NULL,'dbo','entry',0,0)
|
||||
,('ET_currency',0,0,'NCIX_Entry_COL_ET_currency',NULL,'dbo','entry',0,0)
|
||||
|
||||
/* indexe(s) used in central, even if not in pharmacies*/
|
||||
,('ET_entry_type',0,0,'NCIX_Entry_COL_ET_entry_type',NULL,'dbo','entry',0,0)
|
||||
|
||||
/* indexe(s) we really want to drop*/
|
||||
,('ET_master_ID',1,0,'NCIX_Entry_COL_ET_master_ID',NULL,'dbo','entry',0,0)
|
||||
,('ET_bmc_user_profile',1,0,'NCIX_Entry_COL_ET_bmc_user_profile',NULL,'dbo','entry',0,0)
|
||||
,('ET_sales_tax_code',1,0,'NCIX_Entry_COL_ET_sales_tax_code',NULL,'dbo','entry',0,0)
|
||||
,('ET_APS_TS', 1, 0, 'NCIX_Entry_COL_ET_APS_TS',NULL,'dbo','entry',0,0)
|
||||
|
||||
;
|
||||
|
||||
/* check for duplicate */
|
||||
DECLARE @msg VARCHAR(MAX) = '';
|
||||
SELECT @msg = @msg + 'Duplicate index (on expected index name) found in indexes definition. Table ['+[itm].[SchemaName]+'].['+[itm].[TableName]+'], expected index name ['+[itm].[expectedIndexName_inp]+']'+CHAR(13)+CHAR(10)
|
||||
FROM @indexesToMaintains [itm]
|
||||
JOIN (
|
||||
SELECT
|
||||
[ii].[expectedIndexName_inp] AS [key]
|
||||
FROM @indexesToMaintains [ii]
|
||||
GROUP BY [ii].[expectedIndexName_inp]
|
||||
HAVING COUNT(1)>1
|
||||
) d ON d.[key] = [itm].[expectedIndexName_inp]
|
||||
GROUP BY [itm].[SchemaName], [itm].[TableName], [itm].[expectedIndexName_inp]
|
||||
;
|
||||
|
||||
/* stop here if we have an issue in the variable table */
|
||||
IF @msg <> ''
|
||||
BEGIN
|
||||
RAISERROR(@msg, 16, 4);
|
||||
IF @@TRANCOUNT>0
|
||||
BEGIN
|
||||
ROLLBACK TRANSACTION;
|
||||
END
|
||||
RETURN
|
||||
END
|
||||
|
||||
SET @msg = '';
|
||||
SELECT @msg = @msg + 'Duplicate index (on column definition) found in indexes definition. Table ['+[itm].[SchemaName]+'].['+[itm].[TableName]+'], columns in index: '+[itm].[columnsName_inp]
|
||||
+ CASE
|
||||
WHEN [itm].[includedColumns_inp] IS NOT NULL THEN ', included colum(s): '+[itm].[includedColumns_inp]
|
||||
ELSE ''
|
||||
END
|
||||
+CHAR(13)+CHAR(10)
|
||||
FROM @indexesToMaintains [itm]
|
||||
JOIN (
|
||||
SELECT
|
||||
[ii].[columnsName_inp]+'_'+ISNULL([ii].[includedColumns_inp],'') AS [key]
|
||||
FROM @indexesToMaintains [ii]
|
||||
GROUP BY [ii].[columnsName_inp]+'_'+ISNULL([ii].[includedColumns_inp],'')
|
||||
HAVING COUNT(1)>1
|
||||
) d ON d.[key] = [itm].[columnsName_inp]+'_'+ISNULL([itm].[includedColumns_inp],'')
|
||||
GROUP BY [itm].[SchemaName], [itm].[TableName], [itm].[columnsName_inp], [itm].[includedColumns_inp]
|
||||
;
|
||||
|
||||
/* stop here if we have an issue in the variable table */
|
||||
IF @msg <> ''
|
||||
BEGIN
|
||||
RAISERROR(@msg, 16, 4);
|
||||
IF @@TRANCOUNT>0
|
||||
BEGIN
|
||||
ROLLBACK TRANSACTION;
|
||||
END
|
||||
RETURN
|
||||
END
|
||||
|
||||
/* fetch the indexes name on the current instance */
|
||||
DECLARE curIdxName CURSOR FAST_FORWARD READ_ONLY FOR
|
||||
SELECT DISTINCT [itm].[schemaName], [itm].[tableName]
|
||||
FROM @indexesToMaintains [itm];
|
||||
|
||||
OPEN curIdxName;
|
||||
|
||||
FETCH NEXT FROM curIdxName INTO @schemaName, @tableName;
|
||||
|
||||
WHILE @@FETCH_STATUS = 0
|
||||
BEGIN
|
||||
|
||||
;WITH ColInfo
|
||||
AS (
|
||||
SELECT
|
||||
o.[Name] AS TblName
|
||||
,s.[Name] + '.' + o.[Name] AS SchemaTbl
|
||||
,i.[Name] AS IndexName
|
||||
,i.[is_primary_key] AS IsPrimaryKey
|
||||
,i.[is_unique_constraint] AS IsUniqueConstraint
|
||||
,i.[is_unique] AS IsUnique
|
||||
,c.[Name] AS ColName
|
||||
,c.[is_computed] AS IsComputedCol
|
||||
,ic.[is_included_column] AS IsIncludedCol
|
||||
,ic.[key_ordinal]
|
||||
,i.[filter_definition] AS FilterDefinition
|
||||
FROM [sys].[objects] o
|
||||
INNER JOIN [sys].[schemas] s
|
||||
ON o.SCHEMA_ID = s.SCHEMA_ID
|
||||
INNER JOIN [sys].[COLUMNS] c
|
||||
ON o.OBJECT_ID = c.OBJECT_ID
|
||||
INNER JOIN [sys].[indexes] i
|
||||
ON c.OBJECT_ID = i.OBJECT_ID
|
||||
INNER JOIN [sys].[index_columns] ic
|
||||
ON i.[index_id] = ic.[index_id]
|
||||
AND o.OBJECT_ID = ic.OBJECT_ID
|
||||
AND c.[column_id] = ic.[column_id]
|
||||
)
|
||||
|
||||
/* map the list to the actual indexes */
|
||||
UPDATE [itm] SET [itm].[indexName] = i.[name]
|
||||
,[itm].[internal_includedColumnsMatch] = CASE
|
||||
WHEN ISNULL([itm].[includedColumns_inp],'') = ISNULL([idx_cols].[includedColumns],'') THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
,[itm].[internal_actualIncludedColumns] = [idx_cols].[includedColumns]
|
||||
,[itm].[internal_actualColumns] = [idx_cols].[IndexColumns]
|
||||
,[itm].[isIndexFound_comp] = 1
|
||||
,[itm].[isToBeCreated_comp] = 0
|
||||
FROM [sys].[indexes] AS i WITH (NOLOCK)
|
||||
INNER JOIN [sys].[objects] o WITH (NOLOCK)
|
||||
ON i.OBJECT_ID = o.OBJECT_ID
|
||||
OUTER APPLY (
|
||||
SELECT DISTINCT
|
||||
x.TblName
|
||||
,x.IndexName
|
||||
,x.IsPrimaryKey
|
||||
,x.IsUniqueConstraint
|
||||
,x.IsUnique
|
||||
,c.IndexColumns
|
||||
,ci.includedColumns
|
||||
,cc.ComputedColumns
|
||||
,x.FilterDefinition
|
||||
FROM ColInfo x
|
||||
CROSS APPLY (
|
||||
SELECT STUFF(sq.strXML, 1, 2, '') AS IndexColumns
|
||||
FROM (
|
||||
SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName
|
||||
AND x.IndexName = x2.IndexName
|
||||
AND x2.IsIncludedCol = 0
|
||||
ORDER BY x2.[key_ordinal]
|
||||
FOR XML PATH('')
|
||||
) sq(strXML)
|
||||
) c
|
||||
OUTER APPLY (
|
||||
SELECT STUFF(sq.strXML, 1, 2, '') AS includedColumns
|
||||
FROM (
|
||||
SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName
|
||||
AND x.IndexName = x2.IndexName
|
||||
AND x2.IsIncludedCol = 1
|
||||
ORDER BY x2.[key_ordinal]
|
||||
FOR XML PATH('')
|
||||
) sq(strXML)
|
||||
) ci
|
||||
OUTER APPLY (
|
||||
SELECT STUFF(sq.strXML, 1, 2, '') AS ComputedColumns
|
||||
FROM (
|
||||
SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName
|
||||
AND x.IndexName = x2.IndexName
|
||||
AND x2.IsComputedCol = 1
|
||||
ORDER BY x2.[key_ordinal]
|
||||
FOR XML PATH('')
|
||||
) sq(strXML)
|
||||
) cc
|
||||
WHERE x.TblName = o.[Name]
|
||||
AND x.IndexName = i.[Name]
|
||||
) idx_cols
|
||||
LEFT OUTER JOIN (
|
||||
SELECT
|
||||
SCHEMA_NAME(tab.SCHEMA_ID) + '.' + tab.[Name] AS [table]
|
||||
,col.[column_id]
|
||||
,col.[Name] AS [COLUMN_NAME]
|
||||
,CASE
|
||||
WHEN fk.OBJECT_ID IS NOT NULL THEN '>-'
|
||||
ELSE NULL
|
||||
END AS rel
|
||||
,SCHEMA_NAME(pk_tab.SCHEMA_ID) + '.' + pk_tab.[Name] AS primary_table
|
||||
,pk_col.[Name] AS pk_column_name
|
||||
,fk_cols.[constraint_column_id] AS NO
|
||||
,fk.[Name] AS fk_constraint_name
|
||||
,tab.[Name] AS tbl_name
|
||||
FROM [sys].[TABLES] tab
|
||||
INNER JOIN [sys].[COLUMNS] col
|
||||
ON col.OBJECT_ID = tab.OBJECT_ID
|
||||
LEFT OUTER JOIN [sys].[foreign_key_columns] fk_cols
|
||||
ON fk_cols.[parent_object_id] = tab.OBJECT_ID
|
||||
AND fk_cols.[parent_column_id] = col.[column_id]
|
||||
LEFT OUTER JOIN [sys].[foreign_keys] fk
|
||||
ON fk.OBJECT_ID = fk_cols.[constraint_object_id]
|
||||
LEFT OUTER JOIN [sys].[TABLES] pk_tab
|
||||
ON pk_tab.OBJECT_ID = fk_cols.[referenced_object_id]
|
||||
LEFT OUTER JOIN [sys].[COLUMNS] pk_col
|
||||
ON pk_col.[column_id] = fk_cols.[referenced_column_id]
|
||||
AND pk_col.OBJECT_ID = fk_cols.[referenced_object_id]
|
||||
WHERE fk.OBJECT_ID IS NOT NULL
|
||||
) fk
|
||||
ON fk.tbl_name = o.[Name]
|
||||
AND idx_cols.IndexColumns LIKE '%' + fk.[COLUMN_NAME] + '%'
|
||||
INNER JOIN @indexesToMaintains [itm]
|
||||
ON itm.[schemaName] = @schemaName
|
||||
AND itm.[tableName] = @tableName
|
||||
AND itm.[columnsName_inp] COLLATE Latin1_General_CI_AI = [idx_cols].[IndexColumns] COLLATE Latin1_General_CI_AI
|
||||
AND ISNULL([itm].[includedColumns_inp],'') COLLATE Latin1_General_CI_AI = ISNULL([idx_cols].[includedColumns],'') COLLATE Latin1_General_CI_AI
|
||||
WHERE o.TYPE = 'U' -- user table
|
||||
--AND i.[index_id] = s.[index_id]
|
||||
--AND s.[database_id] = DB_ID()
|
||||
AND o.[Name] = @tableName
|
||||
AND SCHEMA_NAME(o.SCHEMA_ID) = @schemaName
|
||||
OPTION (RECOMPILE);
|
||||
|
||||
|
||||
/* Add the indexes not in the list but present on the server to the list */
|
||||
;WITH ColInfo
|
||||
AS (
|
||||
SELECT
|
||||
o.[Name] AS TblName
|
||||
,SCHEMA_NAME(o.[schema_id]) AS SchemaName
|
||||
,s.[Name] + '.' + o.[Name] AS SchemaTbl
|
||||
,i.[Name] AS IndexName
|
||||
,i.[is_primary_key] AS IsPrimaryKey
|
||||
,i.[is_unique_constraint] AS IsUniqueConstraint
|
||||
,i.[is_unique] AS IsUnique
|
||||
,c.[Name] AS ColName
|
||||
,c.[is_computed] AS IsComputedCol
|
||||
,ic.[is_included_column] AS IsIncludedCol
|
||||
,ic.[key_ordinal]
|
||||
,i.[filter_definition] AS FilterDefinition
|
||||
FROM [sys].[objects] o
|
||||
INNER JOIN [sys].[schemas] s
|
||||
ON o.SCHEMA_ID = s.SCHEMA_ID
|
||||
INNER JOIN [sys].[COLUMNS] c
|
||||
ON o.OBJECT_ID = c.OBJECT_ID
|
||||
INNER JOIN [sys].[indexes] i
|
||||
ON c.OBJECT_ID = i.OBJECT_ID
|
||||
INNER JOIN [sys].[index_columns] ic
|
||||
ON i.[index_id] = ic.[index_id]
|
||||
AND o.OBJECT_ID = ic.OBJECT_ID
|
||||
AND c.[column_id] = ic.[column_id]
|
||||
)
|
||||
|
||||
INSERT INTO @indexesToMaintains (
|
||||
[schemaName]
|
||||
,[tableName]
|
||||
,[columnsName_inp]
|
||||
,[indexName]
|
||||
,[isToBeDeleted_inp]
|
||||
,[isToBeDeleted_comp]
|
||||
,[isToBeRecreated_inp]
|
||||
,[internal_statusMsg]
|
||||
,[internal_actualIncludedColumns]
|
||||
,[internal_actualColumns]
|
||||
,[isIndexFound_comp]
|
||||
,[isToBeCreated_comp]
|
||||
,[expectedIndexName_inp]
|
||||
)
|
||||
SELECT DISTINCT
|
||||
@schemaName AS [SchemaName]
|
||||
,@tableName AS [TableName]
|
||||
,c.[IndexColumns] AS [columnsName]
|
||||
,x.[IndexName] AS indexName
|
||||
,0 AS [isToBeDeleted_inp]
|
||||
,CASE
|
||||
WHEN EXISTS(
|
||||
SELECT 1
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE itm.[expectedIndexName_inp] = x.[IndexName]
|
||||
OR ISNULL(itm.[columnsName_inp],'') <> ISNULL(itm.[internal_actualColumns],'')
|
||||
OR ISNULL(itm.[includedColumns_inp],'') <> ISNULL(itm.[internal_actualIncludedColumns],'')
|
||||
) THEN 1
|
||||
WHEN @DoDropExistingIndexesNotReferenced = 1 THEN 1
|
||||
ELSE 0
|
||||
END AS [isToBeDeleted_comp]
|
||||
,0 AS [isToBeRecreated_inp]
|
||||
,CASE
|
||||
WHEN EXISTS(
|
||||
SELECT 1
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE itm.[expectedIndexName_inp] = x.[IndexName]
|
||||
OR ISNULL(itm.[columnsName_inp],'') <> ISNULL(itm.[internal_actualColumns],'')
|
||||
OR ISNULL(itm.[includedColumns_inp],'') <> ISNULL(itm.[internal_actualIncludedColumns],'')
|
||||
) THEN 'Index present locally not as expected, drop before creation'
|
||||
WHEN @DoDropExistingIndexesNotReferenced = 1 THEN 'Index present locally only'
|
||||
ELSE NULL
|
||||
END AS [internal_statusMsg]
|
||||
,ci.[includedColumns] AS [internal_actualIncludedColumns]
|
||||
,c.[IndexColumns] AS [internal_actualColumns]
|
||||
,1 AS [isIndexFound_comp]
|
||||
,0 AS [isToBeCreated_comp]
|
||||
,x.[IndexName] AS [expectedIndexName_inp]
|
||||
FROM ColInfo x
|
||||
CROSS APPLY(SELECT IndexColumns = STUFF(sq.strXML, 1, 2, '')
|
||||
FROM ( SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName AND x.IndexName = x2.IndexName AND x2.IsIncludedCol = 0
|
||||
ORDER BY x2.key_ordinal
|
||||
FOR XML PATH('')
|
||||
) sq (strXML)
|
||||
) c
|
||||
Outer APPLY(SELECT IncludedColumns = STUFF(sq.strXML, 1, 2, '')
|
||||
FROM ( SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName AND x.IndexName = x2.IndexName AND x2.IsIncludedCol = 1
|
||||
ORDER BY x2.key_ordinal
|
||||
FOR XML PATH('')
|
||||
) sq (strXML)
|
||||
) ci
|
||||
Outer APPLY(SELECT ComputedColumns = STUFF(sq.strXML, 1, 2, '')
|
||||
FROM ( SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName AND x.IndexName = x2.IndexName AND x2.IsComputedCol = 1
|
||||
ORDER BY x2.key_ordinal
|
||||
FOR XML PATH('')
|
||||
) sq (strXML)
|
||||
) cc
|
||||
LEFT OUTER JOIN (
|
||||
SELECT
|
||||
SCHEMA_NAME(tab.SCHEMA_ID) + '.' + tab.[Name] AS [table]
|
||||
,col.[column_id]
|
||||
,col.[Name] AS [COLUMN_NAME]
|
||||
,CASE
|
||||
WHEN fk.OBJECT_ID IS NOT NULL THEN '>-'
|
||||
ELSE NULL
|
||||
END AS rel
|
||||
,SCHEMA_NAME(pk_tab.SCHEMA_ID) + '.' + pk_tab.[Name] AS primary_table
|
||||
,pk_col.[Name] AS pk_column_name
|
||||
,fk_cols.[constraint_column_id] AS NO
|
||||
,fk.[Name] AS fk_constraint_name
|
||||
,tab.[Name] AS tbl_name
|
||||
FROM [sys].[TABLES] tab
|
||||
INNER JOIN [sys].[COLUMNS] col
|
||||
ON col.OBJECT_ID = tab.OBJECT_ID
|
||||
LEFT OUTER JOIN [sys].[foreign_key_columns] fk_cols
|
||||
ON fk_cols.[parent_object_id] = tab.OBJECT_ID
|
||||
AND fk_cols.[parent_column_id] = col.[column_id]
|
||||
LEFT OUTER JOIN [sys].[foreign_keys] fk
|
||||
ON fk.OBJECT_ID = fk_cols.[constraint_object_id]
|
||||
LEFT OUTER JOIN [sys].[TABLES] pk_tab
|
||||
ON pk_tab.OBJECT_ID = fk_cols.[referenced_object_id]
|
||||
LEFT OUTER JOIN [sys].[COLUMNS] pk_col
|
||||
ON pk_col.[column_id] = fk_cols.[referenced_column_id]
|
||||
AND pk_col.OBJECT_ID = fk_cols.[referenced_object_id]
|
||||
WHERE fk.OBJECT_ID IS NOT NULL
|
||||
) fk
|
||||
ON fk.tbl_name = x.[TblName]
|
||||
AND [c].[IndexColumns] LIKE '%' + fk.[COLUMN_NAME] + '%'
|
||||
WHERE x.[SchemaName] =@schemaName
|
||||
AND x.[TblName] =@tableName
|
||||
AND NOT EXISTS(
|
||||
SELECT 1
|
||||
FROM @indexesToMaintains [itm2]
|
||||
WHERE 1=1
|
||||
AND ISNULL(itm2.[internal_actualColumns],'') = ISNULL(c.[IndexColumns],'')
|
||||
AND ISNULL(itm2.[internal_actualIncludedColumns],'') = ISNULL(ci.[includedColumns],'')
|
||||
)
|
||||
OPTION (RECOMPILE);
|
||||
|
||||
|
||||
FETCH NEXT FROM curIdxName INTO @schemaName, @tableName;
|
||||
END
|
||||
|
||||
CLOSE curIdxName;
|
||||
DEALLOCATE curIdxName;
|
||||
|
||||
|
||||
/* Adjust the "_comp" flags to create a matrix of actions */
|
||||
/* to be created */
|
||||
UPDATE [itm]
|
||||
SET
|
||||
[itm].[isToBeCreated_comp] = CASE
|
||||
WHEN [itm].[isToBeDeleted_inp] = 0 THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE [itm].[indexName] IS NULL /* index was not found on the server */
|
||||
AND [itm].[expectedIndexName_inp] IS NOT NULL /* we did gave an index name, ie: we want to create it if missing */
|
||||
;
|
||||
|
||||
/* to be renamed */
|
||||
UPDATE [itm]
|
||||
SET
|
||||
[itm].[isToBeRenamed_comp] = 1
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE [itm].[indexName] IS NOT NULL /* index was not found on the server */
|
||||
AND [itm].[expectedIndexName_inp] IS NOT NULL /* we did gave an index name, ie: we expect that index to be present */
|
||||
AND [indexName] <> [itm].[expectedIndexName_inp]
|
||||
AND [isToBeDeleted_inp] = 0
|
||||
AND [isToBeDeleted_comp] = 0
|
||||
;
|
||||
|
||||
/* to be re-created */
|
||||
UPDATE [itm]
|
||||
SET
|
||||
[itm].[isToBeRecreated_comp] = 1
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE [isToBeRecreated_inp] = 1
|
||||
;
|
||||
|
||||
/* to be deleted, because specified in table */
|
||||
UPDATE itm
|
||||
SET
|
||||
[itm].[isToBeDeleted_comp] = CASE
|
||||
WHEN [itm].[isIndexFound_comp] = 0 THEN 0
|
||||
ELSE 1
|
||||
END
|
||||
,[itm].[isToBeRecreated_comp] = 0 /* deletion override re-create */
|
||||
,[itm].[isToBeRenamed_comp] = 0 /* deletion override rename */
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE [itm].[isToBeDeleted_inp] = 1
|
||||
;
|
||||
|
||||
/* to be deleted, because different to specs. link on index name */
|
||||
UPDATE [exp]
|
||||
SET
|
||||
[exp].[isToBeCreated_comp] = 1 /* flag the expected index "to be created" */
|
||||
FROM @indexesToMaintains [exp] --expected
|
||||
JOIN @indexesToMaintains [act] --actual
|
||||
ON [act].[indexName] = [exp].[expectedIndexName_inp]
|
||||
WHERE [exp].[isToBeDeleted_comp] = 0
|
||||
AND [exp].[isToBeCreated_comp] = 0
|
||||
AND [exp].[isToBeRenamed_comp] = 0
|
||||
AND [exp].[isToBeRecreated_inp] = 0
|
||||
AND (
|
||||
[exp].[columnsName_inp] != [act].[internal_actualColumns]
|
||||
OR [exp].[includedColumns_inp] != [act].[internal_actualIncludedColumns]
|
||||
)
|
||||
;
|
||||
|
||||
UPDATE [act]
|
||||
SET
|
||||
[act].[isToBeDeleted_comp] = 1 /* flag the actual index "to be deleted" */
|
||||
FROM @indexesToMaintains [exp] --expected
|
||||
JOIN @indexesToMaintains [act] --actual
|
||||
ON [act].[indexName] = [exp].[expectedIndexName_inp]
|
||||
WHERE (
|
||||
[exp].[columnsName_inp] != [act].[internal_actualColumns]
|
||||
OR [exp].[includedColumns_inp] != [act].[internal_actualIncludedColumns]
|
||||
)
|
||||
;
|
||||
|
||||
/* to be deleted, because different to specs. link on index columns */
|
||||
UPDATE [exp]
|
||||
SET
|
||||
[exp].[isToBeCreated_comp] = 1 /* flag the expected index "to be created" */
|
||||
FROM @indexesToMaintains [exp] --expected
|
||||
JOIN @indexesToMaintains [act] --actual
|
||||
ON [act].[internal_actualColumns] = [exp].[columnsName_inp]
|
||||
WHERE (
|
||||
[exp].[columnsName_inp] != [act].[internal_actualColumns]
|
||||
OR [exp].[includedColumns_inp] != [act].[internal_actualIncludedColumns]
|
||||
)
|
||||
;
|
||||
UPDATE [act]
|
||||
SET
|
||||
[act].[isToBeDeleted_comp] = 1 /* flag the actual index "to be deleted" */
|
||||
FROM @indexesToMaintains [exp] --expected
|
||||
JOIN @indexesToMaintains [act] --actual
|
||||
ON [act].[internal_actualColumns] = [exp].[columnsName_inp]
|
||||
WHERE (
|
||||
[exp].[columnsName_inp] != [act].[internal_actualColumns]
|
||||
OR [exp].[includedColumns_inp] != [act].[internal_actualIncludedColumns]
|
||||
)
|
||||
;
|
||||
|
||||
/* if we have both "rename" and "delete" actions, remove the "rename" action */
|
||||
UPDATE @indexesToMaintains
|
||||
SET [isToBeRenamed_comp] = 0
|
||||
WHERE [isToBeRenamed_comp] = 1
|
||||
AND [isToBeDeleted_comp] = 1
|
||||
;
|
||||
|
||||
/* ensure that we don't have clash between indexes to create and indexes to rename */
|
||||
UPDATE ir
|
||||
SET [ir].[isToBeRenamed_comp] = 0 /* do not rename this index */
|
||||
, [ir].[isToBeDeleted_inp] = 1 /* drop this index instead, as we have one with the correct structure about to be created */
|
||||
FROM @indexesToMaintains [ic] /* to create */
|
||||
JOIN @indexesToMaintains [ir] /* to rename */
|
||||
ON ic.[expectedIndexName_inp] = ir.[expectedIndexName_inp]
|
||||
WHERE [ic].[isToBeCreated_comp] = 1
|
||||
AND [ir].[isToBeRenamed_comp] = 1
|
||||
|
||||
/* Show the action matrix */
|
||||
SELECT [itm].[isIndexFound_comp]
|
||||
,[itm].[isToBeCreated_comp]
|
||||
,[itm].[isToBeRenamed_comp]
|
||||
,[itm].[isToBeDeleted_comp]
|
||||
,[itm].[isToBeRecreated_comp]
|
||||
,[itm].[internal_statusMsg]
|
||||
,'....'
|
||||
,[itm].[isToBeDeleted_inp]
|
||||
,[itm].[isToBeRecreated_inp]
|
||||
,[itm].[indexName]
|
||||
,[itm].[expectedIndexName_inp]
|
||||
,[itm].[columnsName_inp]
|
||||
,[itm].[internal_actualColumns]
|
||||
,[itm].[includedColumns_inp]
|
||||
,[itm].[internal_actualIncludedColumns]
|
||||
FROM @indexesToMaintains [itm]
|
||||
ORDER BY [itm].[isIndexFound_comp],[itm].[isToBeDeleted_inp], [itm].[columnsName_inp];
|
||||
|
||||
|
||||
/* Drop the indexe(s) that are to be deleted or recreated */
|
||||
SET @query='';
|
||||
SELECT @query = @query + 'DROP INDEX '+[itm].[indexName]+' ON dbo.entry;'+CHAR(13)+CHAR(10)
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE [itm].[isToBeDeleted_comp] = 1
|
||||
OR [itm].[isToBeRecreated_comp] = 1
|
||||
;
|
||||
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT '-- execute DROP INDEX';
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT @query;
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT CHAR(13)+CHAR(10);
|
||||
|
||||
IF @DoOnlyOutputStatement = 0
|
||||
BEGIN
|
||||
EXECUTE(@query);
|
||||
END
|
||||
|
||||
/* rename existing indexe(s) */
|
||||
SET @query = '';
|
||||
SELECT @query = @query + 'EXEC sp_rename @objname ='''+[itm].[tableName]+'.'+[itm].[indexName]+''', @newname = '''+[itm].[expectedIndexName_inp]+''';'+CHAR(13)+CHAR(10)
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE [itm].[isToBeRenamed_comp] = 1
|
||||
;
|
||||
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT '-- execute sp_rename';
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT @query;
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT CHAR(13)+CHAR(10);
|
||||
|
||||
IF @DoOnlyOutputStatement = 0
|
||||
BEGIN
|
||||
EXECUTE(@query);
|
||||
END
|
||||
|
||||
/* create indexe(s) */
|
||||
SET @query='';
|
||||
SELECT @query = @query + 'CREATE '
|
||||
+CASE WHEN [itm].[isClustered_inp]=1 THEN 'CLUSTERED' ELSE 'NONCLUSTERED' END
|
||||
+CASE WHEN [itm].[isUnique_inp]=1 THEN ' UNIQUE' ELSE '' END
|
||||
+' INDEX '+[itm].[expectedIndexName_inp]
|
||||
+' ON '+[itm].[schemaName]+'.'+[itm].[tableName]+'('+[itm].[columnsName_inp]+')'
|
||||
+ CASE
|
||||
WHEN [itm].[includedColumns_inp] IS NOT NULL THEN ' INCLUDE ('+[itm].[includedColumns_inp]+')'
|
||||
ELSE ''
|
||||
END
|
||||
+';'
|
||||
+CHAR(13)+CHAR(10)
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE (
|
||||
[itm].[isToBeCreated_comp] = 1
|
||||
OR [itm].[isToBeRecreated_comp] = 1
|
||||
)
|
||||
;
|
||||
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT '-- execute CREATE INDEX';
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT @query;
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT CHAR(13)+CHAR(10);
|
||||
|
||||
IF @DoOnlyOutputStatement = 0
|
||||
BEGIN
|
||||
EXECUTE(@query);
|
||||
END
|
||||
|
||||
--ROLLBACK TRANSACTION;
|
||||
COMMIT TRANSACTION
|
||||
800
OCTPDBA-414 - proc to align indexes/proc.sql
Normal file
800
OCTPDBA-414 - proc to align indexes/proc.sql
Normal file
@@ -0,0 +1,800 @@
|
||||
USE Arizona;
|
||||
GO
|
||||
IF OBJECT_ID('upd.alignIndexes') IS NOT NULL
|
||||
DROP PROCEDURE [upd].alignIndexes;
|
||||
GO
|
||||
|
||||
/*=============================================================================
|
||||
|
||||
OCTPDBA-414
|
||||
This procedure is used to align indexes in a pharmacy against a template, stored in the table [arizona].[upd].[IndexesAlignementActions]
|
||||
|
||||
Note that:
|
||||
* Matching is always made from the columns of the index, never on the name of the index.
|
||||
The reason is that we might have difference in the name of the index between several servers.
|
||||
* If an index exists with the name A, but your list contains a similar index with the name B, index A will be renamed to B with sp_rename
|
||||
|
||||
Parameters
|
||||
----------------------
|
||||
@in_debug
|
||||
Debug level. Default 0
|
||||
0 = no debug, execute commands
|
||||
1 = print commands and output a matrix showing the found state
|
||||
2 = only print commands and output a matrix showing the found state
|
||||
|
||||
@in_dropUnreferencedIndexes
|
||||
Drop indexes not referenced. Default 0
|
||||
This flag govern behavior when we have a index on a table that exists in [IndexesAlignementActions], but that this specific index is not present in [IndexesAlignementActions]
|
||||
0 = Leave the unknown index in place
|
||||
1 = Drop the unknown index
|
||||
|
||||
Context
|
||||
----------------------
|
||||
This proc can be called at anytime to align indexes against those referenced in [arizona].[upd].[IndexesAlignementActions]
|
||||
|
||||
Creation : 03.02.2023 / TSC
|
||||
Modifications:
|
||||
|
||||
=============================================================================*/
|
||||
CREATE PROCEDURE [upd].[alignIndexes]
|
||||
@in_debug INT = 0,
|
||||
@in_dropUnreferencedIndexes BIT = 0
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
/* variables */
|
||||
DECLARE @query VARCHAR(MAX); /* for dynamic sql */
|
||||
DECLARE @outputStatement BIT = CASE /* Do we want to have the commands printed out ? */
|
||||
WHEN @in_debug IN ( 1, 2 ) THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
END;
|
||||
DECLARE @executeStatement BIT = CASE /* Do we want to execute the commands ? */
|
||||
WHEN @in_debug IN ( 0, 1 ) THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
END;
|
||||
DECLARE @schemaName VARCHAR(100); /* used in cursor */
|
||||
DECLARE @tableName VARCHAR(100); /* used in cursor */
|
||||
DECLARE @indexFK INT; /* used in cursor */
|
||||
DECLARE @msg VARCHAR(MAX) = '';
|
||||
DECLARE @indexesToMaintains TABLE
|
||||
(
|
||||
[IA_indexesAlignementActions] INT NULL, /* FK to table upd.IA_IndexesAlignementActions */
|
||||
[SchemaName] VARCHAR(100) NOT NULL, /* the schema the table is part of */
|
||||
[TableName] VARCHAR(100) NOT NULL, /* On which table is the index, whithout the schema */
|
||||
columnsName_inp VARCHAR(MAX) NOT NULL, /* list all the columns of the index, in the correct orders */
|
||||
IA_index_options VARCHAR(MAX) NULL, /* index options */
|
||||
isClustered_inp BIT NOT NULL
|
||||
DEFAULT 0, /* Is the indexe a clustered index ? */
|
||||
isUnique_inp BIT NOT NULL
|
||||
DEFAULT 0, /* Is the index unique ? */
|
||||
includedColumns_inp VARCHAR(MAX) NULL, /* list all the included columns the index should have. only relevant for idx not to be dropped */
|
||||
isToBeDeleted_inp BIT NOT NULL
|
||||
DEFAULT 0, /* must the script drop this index ? */
|
||||
isToBeRecreated_inp BIT NOT NULL
|
||||
DEFAULT 0, /* must the script recreate this index ?
|
||||
If an existing index differs from the definition, it will be dropped and the correct one created.
|
||||
Use this only to force the re-creation even if the structure is identical */
|
||||
expectedIndexName_inp VARCHAR(MAX) NULL, /* the name the index should have, used to determine if a rename of the existing index should be done */
|
||||
indexName VARCHAR(MAX) NULL, /* computed by the script. The index name on this system, as indexes name can be different accross systems*/
|
||||
isIndexFound_comp BIT NOT NULL
|
||||
DEFAULT 0, /* computed by the script. set to 1 if the index is present on the server */
|
||||
isToBeCreated_comp BIT NULL
|
||||
DEFAULT 0, /* computed by the script. does this index will be created on the server ? */
|
||||
isToBeRenamed_comp BIT NULL
|
||||
DEFAULT 0, /* computed by the script. does this index will be renamed ? */
|
||||
isToBeDeleted_comp BIT NULL
|
||||
DEFAULT 0, /* computed by the script. does this index will be deleted ? */
|
||||
isToBeRecreated_comp BIT NULL
|
||||
DEFAULT 0, /* computed by the script. does this index will be re-created ? */
|
||||
includedColumnsMatch_internal BIT NULL, /* computed ba the script. Are the expected and actual included columns identical ? */
|
||||
actualColumns_internal VARCHAR(MAX) NULL, /* the actual columns in the existing index */
|
||||
actualIncludedColumns_internal VARCHAR(MAX) NULL, /* the actual columns in the INCLUDE part of the index */
|
||||
statusMsg_internal VARCHAR(MAX) NULL /* Message, used for debug */
|
||||
);
|
||||
|
||||
|
||||
/* fetch index to align from upd.IA_IndexesAlignementActions */
|
||||
INSERT INTO @indexesToMaintains
|
||||
(
|
||||
[IA_indexesAlignementActions],
|
||||
[SchemaName],
|
||||
[TableName],
|
||||
expectedIndexName_inp,
|
||||
columnsName_inp,
|
||||
includedColumns_inp,
|
||||
isClustered_inp,
|
||||
isUnique_inp,
|
||||
isToBeDeleted_inp,
|
||||
isToBeRecreated_inp,
|
||||
IA_index_options
|
||||
)
|
||||
SELECT ia.[IA_indexesAlignementActions_id],
|
||||
ia.[IA_schema_name],
|
||||
ia.[IA_table_name],
|
||||
ia.[IA_expected_index_name],
|
||||
ia.[IA_columns_name],
|
||||
ia.[IA_included_columns],
|
||||
ia.[IA_is_clustered],
|
||||
ia.[IA_is_unique],
|
||||
ia.[IA_is_to_be_deleted],
|
||||
ia.[IA_is_to_be_recreated],
|
||||
ia.IA_index_options
|
||||
FROM [upd].[IA_IndexesAlignementActions] ia
|
||||
WHERE ia.[IA_executionDate] IS NULL;
|
||||
|
||||
|
||||
/* logic checks on index definition table */
|
||||
SELECT @msg
|
||||
= @msg + 'Duplicate index (on expected index name) found in indexes definition. Table ['
|
||||
+ [itm].[IA_schema_name] + '].[' + [itm].[IA_table_name] + '], expected index name ['
|
||||
+ [itm].[IA_expected_index_name] + ']' + CHAR(13) + CHAR(10)
|
||||
FROM [upd].[IA_IndexesAlignementActions] [itm]
|
||||
JOIN
|
||||
(
|
||||
SELECT [ii].[IA_expected_index_name] AS [key]
|
||||
FROM [upd].[IA_IndexesAlignementActions] [ii]
|
||||
GROUP BY [ii].[IA_expected_index_name]
|
||||
HAVING COUNT(1) > 1
|
||||
) d
|
||||
ON d.[key] = [itm].[IA_expected_index_name]
|
||||
GROUP BY [itm].[IA_schema_name],
|
||||
[itm].[IA_table_name],
|
||||
[itm].[IA_expected_index_name];
|
||||
|
||||
--duplicate index key
|
||||
SELECT @msg
|
||||
= @msg + 'Duplicate index (on column definition) found in indexes definition. Table [' + [itm].[IA_schema_name]
|
||||
+ '].[' + [itm].[IA_table_name] + '], columns in index: ' + [itm].[IA_columns_name]
|
||||
+ CASE
|
||||
WHEN [itm].[IA_included_columns] IS NOT NULL THEN
|
||||
', included colum(s): ' + [itm].[IA_included_columns]
|
||||
ELSE
|
||||
''
|
||||
END + CHAR(13) + CHAR(10)
|
||||
FROM [upd].[IA_IndexesAlignementActions] [itm]
|
||||
JOIN
|
||||
(
|
||||
SELECT [ii].[IA_columns_name] + '_' + ISNULL([ii].[IA_included_columns], '') AS [key]
|
||||
FROM [upd].[IA_IndexesAlignementActions] [ii]
|
||||
GROUP BY [ii].[IA_columns_name] + '_' + ISNULL([ii].[IA_included_columns], '')
|
||||
HAVING COUNT(1) > 1
|
||||
) d
|
||||
ON d.[key] = [itm].[IA_columns_name] + '_' + ISNULL([itm].[IA_included_columns], '')
|
||||
GROUP BY [itm].[IA_schema_name],
|
||||
[itm].[IA_table_name],
|
||||
[itm].[IA_columns_name],
|
||||
[itm].[IA_included_columns];
|
||||
|
||||
IF @msg <> ''
|
||||
BEGIN
|
||||
RAISERROR(@msg, 16, 4);
|
||||
IF @@TRANCOUNT > 0
|
||||
BEGIN
|
||||
ROLLBACK TRANSACTION;
|
||||
END;
|
||||
RETURN 1;
|
||||
END;
|
||||
|
||||
|
||||
/* fetch the indexes name and non listed indexes on the current instance */
|
||||
DECLARE curIdxName CURSOR FAST_FORWARD READ_ONLY FOR
|
||||
SELECT DISTINCT
|
||||
[itm].[IA_schema_name],
|
||||
[itm].[IA_table_name],
|
||||
itm.[IA_indexesAlignementActions_id]
|
||||
FROM [upd].[IA_IndexesAlignementActions] [itm];
|
||||
|
||||
OPEN curIdxName;
|
||||
|
||||
FETCH NEXT FROM curIdxName
|
||||
INTO @schemaName,
|
||||
@tableName,
|
||||
@indexFK;
|
||||
|
||||
WHILE @@FETCH_STATUS = 0
|
||||
BEGIN
|
||||
/* map the list to the actual indexes */
|
||||
WITH ColInfo
|
||||
AS (SELECT o.[name] AS TblName,
|
||||
s.[name] + '.' + o.[name] AS SchemaTbl,
|
||||
i.[name] AS IndexName,
|
||||
i.[is_primary_key] AS IsPrimaryKey,
|
||||
i.[is_unique_constraint] AS IsUniqueConstraint,
|
||||
i.[is_unique] AS IsUnique,
|
||||
c.[name] AS ColName,
|
||||
c.[is_computed] AS IsComputedCol,
|
||||
ic.[is_included_column] AS IsIncludedCol,
|
||||
ic.[key_ordinal],
|
||||
i.[filter_definition] AS FilterDefinition,
|
||||
i.type AS indexType /* 1=clustered, 2=non clustered */
|
||||
FROM [sys].[objects] o
|
||||
INNER JOIN [sys].[schemas] s
|
||||
ON o.schema_id = s.schema_id
|
||||
INNER JOIN [sys].[columns] c
|
||||
ON o.object_id = c.object_id
|
||||
INNER JOIN [sys].[indexes] i
|
||||
ON c.object_id = i.object_id
|
||||
INNER JOIN [sys].[index_columns] ic
|
||||
ON i.[index_id] = ic.[index_id]
|
||||
AND o.object_id = ic.object_id
|
||||
AND c.[column_id] = ic.[column_id])
|
||||
UPDATE [itm]
|
||||
SET [itm].[indexName] = i.[name],
|
||||
[itm].[includedColumnsMatch_internal] = CASE
|
||||
WHEN ISNULL([itm].[includedColumns_inp], '') = ISNULL(
|
||||
[idx_cols].[includedColumns],
|
||||
''
|
||||
) THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
END,
|
||||
[itm].[actualIncludedColumns_internal] = [idx_cols].[includedColumns],
|
||||
[itm].[actualColumns_internal] = [idx_cols].[IndexColumns],
|
||||
[itm].[isIndexFound_comp] = 1,
|
||||
[itm].[isToBeCreated_comp] = 0,
|
||||
[itm].[isToBeRecreated_comp] = CASE
|
||||
WHEN idx_cols.indexType <> 1
|
||||
AND [itm].isClustered_inp = 1
|
||||
AND idx_cols.IsPrimaryKey = 0 THEN
|
||||
1 /* existing index is not clustered and not the PK, recreate */
|
||||
ELSE
|
||||
0
|
||||
END
|
||||
FROM [sys].[indexes] AS i WITH (NOLOCK)
|
||||
INNER JOIN [sys].[objects] o WITH (NOLOCK)
|
||||
ON i.object_id = o.object_id
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT DISTINCT
|
||||
x.TblName,
|
||||
x.IndexName,
|
||||
x.IsPrimaryKey,
|
||||
x.IsUniqueConstraint,
|
||||
x.IsUnique,
|
||||
c.IndexColumns,
|
||||
ci.includedColumns,
|
||||
cc.ComputedColumns,
|
||||
x.FilterDefinition,
|
||||
x.indexType
|
||||
FROM ColInfo x
|
||||
CROSS APPLY
|
||||
(
|
||||
SELECT STUFF(sq.strXML, 1, 2, '') AS IndexColumns
|
||||
FROM
|
||||
(
|
||||
SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName
|
||||
AND x.IndexName = x2.IndexName
|
||||
AND x2.IsIncludedCol = 0
|
||||
ORDER BY x2.[key_ordinal]
|
||||
FOR XML PATH('')
|
||||
) sq(strXML)
|
||||
) c
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT STUFF(sq.strXML, 1, 2, '') AS includedColumns
|
||||
FROM
|
||||
(
|
||||
SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName
|
||||
AND x.IndexName = x2.IndexName
|
||||
AND x2.IsIncludedCol = 1
|
||||
ORDER BY x2.[key_ordinal]
|
||||
FOR XML PATH('')
|
||||
) sq(strXML)
|
||||
) ci
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT STUFF(sq.strXML, 1, 2, '') AS ComputedColumns
|
||||
FROM
|
||||
(
|
||||
SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName
|
||||
AND x.IndexName = x2.IndexName
|
||||
AND x2.IsComputedCol = 1
|
||||
ORDER BY x2.[key_ordinal]
|
||||
FOR XML PATH('')
|
||||
) sq(strXML)
|
||||
) cc
|
||||
WHERE x.TblName = o.[name]
|
||||
AND x.IndexName = i.[name]
|
||||
) idx_cols
|
||||
LEFT OUTER JOIN
|
||||
(
|
||||
SELECT SCHEMA_NAME(tab.schema_id) + '.' + tab.[name] AS [table],
|
||||
col.[column_id],
|
||||
col.[name] AS [COLUMN_NAME],
|
||||
CASE
|
||||
WHEN fk.object_id IS NOT NULL THEN
|
||||
'>-'
|
||||
ELSE
|
||||
NULL
|
||||
END AS rel,
|
||||
SCHEMA_NAME(pk_tab.schema_id) + '.' + pk_tab.[name] AS primary_table,
|
||||
pk_col.[name] AS pk_column_name,
|
||||
fk_cols.[constraint_column_id] AS NO,
|
||||
fk.[name] AS fk_constraint_name,
|
||||
tab.[name] AS tbl_name
|
||||
FROM [sys].[tables] tab
|
||||
INNER JOIN [sys].[columns] col
|
||||
ON col.object_id = tab.object_id
|
||||
LEFT OUTER JOIN [sys].[foreign_key_columns] fk_cols
|
||||
ON fk_cols.[parent_object_id] = tab.object_id
|
||||
AND fk_cols.[parent_column_id] = col.[column_id]
|
||||
LEFT OUTER JOIN [sys].[foreign_keys] fk
|
||||
ON fk.object_id = fk_cols.[constraint_object_id]
|
||||
LEFT OUTER JOIN [sys].[tables] pk_tab
|
||||
ON pk_tab.object_id = fk_cols.[referenced_object_id]
|
||||
LEFT OUTER JOIN [sys].[columns] pk_col
|
||||
ON pk_col.[column_id] = fk_cols.[referenced_column_id]
|
||||
AND pk_col.object_id = fk_cols.[referenced_object_id]
|
||||
WHERE fk.object_id IS NOT NULL
|
||||
) fk
|
||||
ON fk.tbl_name = o.[name]
|
||||
AND idx_cols.IndexColumns LIKE '%' + fk.[COLUMN_NAME] + '%'
|
||||
INNER JOIN @indexesToMaintains [itm]
|
||||
ON itm.[SchemaName] = @schemaName
|
||||
AND itm.[TableName] = @tableName
|
||||
AND itm.[columnsName_inp] COLLATE Latin1_General_CI_AI = [idx_cols].[IndexColumns] COLLATE Latin1_General_CI_AI
|
||||
AND ISNULL([itm].[includedColumns_inp], '')COLLATE Latin1_General_CI_AI = ISNULL(
|
||||
[idx_cols].[includedColumns],
|
||||
''
|
||||
)COLLATE Latin1_General_CI_AI
|
||||
WHERE o.type = 'U' -- user table
|
||||
--AND i.[index_id] = s.[index_id]
|
||||
--AND s.[database_id] = DB_ID()
|
||||
AND o.[name] = @tableName
|
||||
AND SCHEMA_NAME(o.schema_id) = @schemaName
|
||||
OPTION (RECOMPILE);
|
||||
|
||||
|
||||
/* Add the indexes not in the list but present on the server to the list */
|
||||
WITH ColInfo
|
||||
AS (SELECT o.[name] AS TblName,
|
||||
SCHEMA_NAME(o.[schema_id]) AS [SchemaName],
|
||||
s.[name] + '.' + o.[name] AS SchemaTbl,
|
||||
i.[name] AS IndexName,
|
||||
i.[is_primary_key] AS IsPrimaryKey,
|
||||
i.[is_unique_constraint] AS IsUniqueConstraint,
|
||||
i.[is_unique] AS IsUnique,
|
||||
c.[name] AS ColName,
|
||||
c.[is_computed] AS IsComputedCol,
|
||||
ic.[is_included_column] AS IsIncludedCol,
|
||||
ic.[key_ordinal],
|
||||
i.[filter_definition] AS FilterDefinition
|
||||
FROM [sys].[objects] o
|
||||
INNER JOIN [sys].[schemas] s
|
||||
ON o.schema_id = s.schema_id
|
||||
INNER JOIN [sys].[columns] c
|
||||
ON o.object_id = c.object_id
|
||||
INNER JOIN [sys].[indexes] i
|
||||
ON c.object_id = i.object_id
|
||||
INNER JOIN [sys].[index_columns] ic
|
||||
ON i.[index_id] = ic.[index_id]
|
||||
AND o.object_id = ic.object_id
|
||||
AND c.[column_id] = ic.[column_id])
|
||||
INSERT INTO @indexesToMaintains
|
||||
(
|
||||
[SchemaName],
|
||||
[TableName],
|
||||
[columnsName_inp],
|
||||
[indexName],
|
||||
[isToBeDeleted_inp],
|
||||
[isToBeDeleted_comp],
|
||||
[isToBeRecreated_inp],
|
||||
[statusMsg_internal],
|
||||
[actualIncludedColumns_internal],
|
||||
[actualColumns_internal],
|
||||
[isIndexFound_comp],
|
||||
[isToBeCreated_comp],
|
||||
[expectedIndexName_inp]
|
||||
)
|
||||
SELECT DISTINCT
|
||||
@schemaName AS [SchemaName],
|
||||
@tableName AS [TableName],
|
||||
c.[IndexColumns] AS [columnsName],
|
||||
x.[IndexName] AS indexName,
|
||||
0 AS [isToBeDeleted_inp],
|
||||
CASE
|
||||
WHEN EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE itm.[expectedIndexName_inp] = x.[IndexName]
|
||||
OR ISNULL(itm.[columnsName_inp], '') <> ISNULL(itm.[actualColumns_internal], '')
|
||||
OR ISNULL(itm.[includedColumns_inp], '') <> ISNULL(
|
||||
itm.[actualIncludedColumns_internal],
|
||||
''
|
||||
)
|
||||
) THEN
|
||||
1
|
||||
WHEN @in_dropUnreferencedIndexes = 1 THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
END AS [isToBeDeleted_comp],
|
||||
0 AS [isToBeRecreated_inp],
|
||||
CASE
|
||||
WHEN EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE itm.[expectedIndexName_inp] = x.[IndexName]
|
||||
OR ISNULL(itm.[columnsName_inp], '') <> ISNULL(itm.[actualColumns_internal], '')
|
||||
OR ISNULL(itm.[includedColumns_inp], '') <> ISNULL(
|
||||
itm.[actualIncludedColumns_internal],
|
||||
''
|
||||
)
|
||||
) THEN
|
||||
'Index present locally not as expected, drop before creation'
|
||||
WHEN @in_dropUnreferencedIndexes = 1 THEN
|
||||
'Index present locally only'
|
||||
ELSE
|
||||
NULL
|
||||
END AS [statusMsg_internal],
|
||||
ci.[IncludedColumns] AS [actualIncludedColumns_internal],
|
||||
c.[IndexColumns] AS [actualColumns_internal],
|
||||
1 AS [isIndexFound_comp],
|
||||
0 AS [isToBeCreated_comp],
|
||||
x.[IndexName] AS [expectedIndexName_inp]
|
||||
FROM ColInfo x
|
||||
CROSS APPLY
|
||||
(
|
||||
SELECT IndexColumns = STUFF(sq.strXML, 1, 2, '')
|
||||
FROM
|
||||
(
|
||||
SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName
|
||||
AND x.IndexName = x2.IndexName
|
||||
AND x2.IsIncludedCol = 0
|
||||
ORDER BY x2.[key_ordinal]
|
||||
FOR XML PATH('')
|
||||
) sq(strXML)
|
||||
) c
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT IncludedColumns = STUFF(sq.strXML, 1, 2, '')
|
||||
FROM
|
||||
(
|
||||
SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName
|
||||
AND x.IndexName = x2.IndexName
|
||||
AND x2.IsIncludedCol = 1
|
||||
ORDER BY x2.[key_ordinal]
|
||||
FOR XML PATH('')
|
||||
) sq(strXML)
|
||||
) ci
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT ComputedColumns = STUFF(sq.strXML, 1, 2, '')
|
||||
FROM
|
||||
(
|
||||
SELECT ', ' + ISNULL(x2.ColName, '')
|
||||
FROM ColInfo x2
|
||||
WHERE x.TblName = x2.TblName
|
||||
AND x.IndexName = x2.IndexName
|
||||
AND x2.IsComputedCol = 1
|
||||
ORDER BY x2.[key_ordinal]
|
||||
FOR XML PATH('')
|
||||
) sq(strXML)
|
||||
) cc
|
||||
LEFT OUTER JOIN
|
||||
(
|
||||
SELECT SCHEMA_NAME(tab.schema_id) + '.' + tab.[name] AS [table],
|
||||
col.[column_id],
|
||||
col.[name] AS [COLUMN_NAME],
|
||||
CASE
|
||||
WHEN fk.object_id IS NOT NULL THEN
|
||||
'>-'
|
||||
ELSE
|
||||
NULL
|
||||
END AS rel,
|
||||
SCHEMA_NAME(pk_tab.schema_id) + '.' + pk_tab.[name] AS primary_table,
|
||||
pk_col.[name] AS pk_column_name,
|
||||
fk_cols.[constraint_column_id] AS NO,
|
||||
fk.[name] AS fk_constraint_name,
|
||||
tab.[name] AS tbl_name
|
||||
FROM [sys].[tables] tab
|
||||
INNER JOIN [sys].[columns] col
|
||||
ON col.object_id = tab.object_id
|
||||
LEFT OUTER JOIN [sys].[foreign_key_columns] fk_cols
|
||||
ON fk_cols.[parent_object_id] = tab.object_id
|
||||
AND fk_cols.[parent_column_id] = col.[column_id]
|
||||
LEFT OUTER JOIN [sys].[foreign_keys] fk
|
||||
ON fk.object_id = fk_cols.[constraint_object_id]
|
||||
LEFT OUTER JOIN [sys].[tables] pk_tab
|
||||
ON pk_tab.object_id = fk_cols.[referenced_object_id]
|
||||
LEFT OUTER JOIN [sys].[columns] pk_col
|
||||
ON pk_col.[column_id] = fk_cols.[referenced_column_id]
|
||||
AND pk_col.object_id = fk_cols.[referenced_object_id]
|
||||
WHERE fk.object_id IS NOT NULL
|
||||
) fk
|
||||
ON fk.tbl_name = x.[TblName]
|
||||
AND [c].[IndexColumns] LIKE '%' + fk.[COLUMN_NAME] + '%'
|
||||
WHERE x.[SchemaName] = @schemaName
|
||||
AND x.[TblName] = @tableName
|
||||
AND NOT EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
FROM @indexesToMaintains [itm2]
|
||||
WHERE 1 = 1
|
||||
AND ISNULL(itm2.[actualColumns_internal], '') = ISNULL(c.[IndexColumns], '')
|
||||
AND ISNULL(itm2.[actualIncludedColumns_internal], '') = ISNULL(ci.[IncludedColumns], '')
|
||||
)
|
||||
OPTION (RECOMPILE);
|
||||
|
||||
|
||||
FETCH NEXT FROM curIdxName
|
||||
INTO @schemaName,
|
||||
@tableName,
|
||||
@indexFK;
|
||||
END;
|
||||
|
||||
CLOSE curIdxName;
|
||||
DEALLOCATE curIdxName;
|
||||
|
||||
|
||||
/* Adjust the "_comp" flags to create a matrix of actions */
|
||||
/* to be created */
|
||||
UPDATE [itm]
|
||||
SET [itm].[isToBeCreated_comp] = CASE
|
||||
WHEN [itm].[isToBeDeleted_inp] = 0 THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
END
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE [itm].[indexName] IS NULL /* index was not found on the server */
|
||||
AND [itm].[expectedIndexName_inp] IS NOT NULL /* we did gave an index name, ie: we want to create it if missing */
|
||||
;
|
||||
|
||||
/* to be renamed */
|
||||
UPDATE [itm]
|
||||
SET [itm].[isToBeRenamed_comp] = 1
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE [itm].[indexName] IS NOT NULL /* index was not found on the server */
|
||||
AND [itm].[expectedIndexName_inp] IS NOT NULL /* we did gave an index name, ie: we expect that index to be present */
|
||||
AND [indexName] <> [itm].[expectedIndexName_inp]
|
||||
AND [isToBeDeleted_inp] = 0
|
||||
AND [isToBeDeleted_comp] = 0
|
||||
AND [isToBeRecreated_inp] = 0
|
||||
AND [isToBeRecreated_comp] = 0;
|
||||
|
||||
/* to be re-created */
|
||||
UPDATE [itm]
|
||||
SET [itm].[isToBeRecreated_comp] = 1
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE [isToBeRecreated_inp] = 1;
|
||||
|
||||
--/* to be re-created because wrong index type*/
|
||||
--UPDATE [itm]
|
||||
--SET [itm].[isToBeRecreated_comp] = 1
|
||||
--FROM @indexesToMaintains [itm]
|
||||
--WHERE [itm].isClustered_inp = 1
|
||||
--AND itm.;
|
||||
|
||||
/* to be deleted, because specified in table */
|
||||
UPDATE itm
|
||||
SET [itm].[isToBeDeleted_comp] = CASE
|
||||
WHEN [itm].[isIndexFound_comp] = 0 THEN
|
||||
0
|
||||
ELSE
|
||||
1
|
||||
END,
|
||||
[itm].[isToBeRecreated_comp] = 0, /* deletion override re-create */
|
||||
[itm].[isToBeRenamed_comp] = 0 /* deletion override rename */
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE [itm].[isToBeDeleted_inp] = 1;
|
||||
|
||||
/* to be deleted, because different to specs. link on index name */
|
||||
UPDATE [exp]
|
||||
SET [exp].[isToBeCreated_comp] = 1 /* flag the expected index "to be created" */
|
||||
FROM @indexesToMaintains [exp] --expected
|
||||
JOIN @indexesToMaintains [act] --actual
|
||||
ON [act].[indexName] = [exp].[expectedIndexName_inp]
|
||||
WHERE [exp].[isToBeDeleted_comp] = 0
|
||||
AND [exp].[isToBeCreated_comp] = 0
|
||||
AND [exp].[isToBeRenamed_comp] = 0
|
||||
AND [exp].[isToBeRecreated_inp] = 0
|
||||
AND
|
||||
(
|
||||
[exp].[columnsName_inp] != [act].[actualColumns_internal]
|
||||
OR [exp].[includedColumns_inp] != [act].[actualIncludedColumns_internal]
|
||||
);
|
||||
|
||||
UPDATE [act]
|
||||
SET [act].[isToBeDeleted_comp] = 1 /* flag the actual index "to be deleted" */
|
||||
FROM @indexesToMaintains [exp] --expected
|
||||
JOIN @indexesToMaintains [act] --actual
|
||||
ON [act].[indexName] = [exp].[expectedIndexName_inp]
|
||||
WHERE (
|
||||
[exp].[columnsName_inp] != [act].[actualColumns_internal]
|
||||
OR [exp].[includedColumns_inp] != [act].[actualIncludedColumns_internal]
|
||||
);
|
||||
|
||||
/* to be deleted, because different to specs. link on index columns */
|
||||
UPDATE [exp]
|
||||
SET [exp].[isToBeCreated_comp] = 1 /* flag the expected index "to be created" */
|
||||
FROM @indexesToMaintains [exp] --expected
|
||||
JOIN @indexesToMaintains [act] --actual
|
||||
ON [act].[actualColumns_internal] = [exp].[columnsName_inp]
|
||||
WHERE (
|
||||
[exp].[columnsName_inp] != [act].[actualColumns_internal]
|
||||
OR [exp].[includedColumns_inp] != [act].[actualIncludedColumns_internal]
|
||||
);
|
||||
|
||||
UPDATE [act]
|
||||
SET [act].[isToBeDeleted_comp] = 1 /* flag the actual index "to be deleted" */
|
||||
FROM @indexesToMaintains [exp] --expected
|
||||
JOIN @indexesToMaintains [act] --actual
|
||||
ON [act].[actualColumns_internal] = [exp].[columnsName_inp]
|
||||
WHERE (
|
||||
[exp].[columnsName_inp] != [act].[actualColumns_internal]
|
||||
OR [exp].[includedColumns_inp] != [act].[actualIncludedColumns_internal]
|
||||
);
|
||||
|
||||
/* if we have both "rename" and "delete" actions, remove the "rename" action */
|
||||
UPDATE @indexesToMaintains
|
||||
SET [isToBeRenamed_comp] = 0
|
||||
WHERE [isToBeRenamed_comp] = 1
|
||||
AND [isToBeDeleted_comp] = 1;
|
||||
|
||||
/* ensure that we don't have clash between indexes to create and indexes to rename */
|
||||
UPDATE ir
|
||||
SET [ir].[isToBeRenamed_comp] = 0, /* do not rename this index */
|
||||
[ir].[isToBeDeleted_inp] = 1 /* drop this index instead, as we have one with the correct structure about to be created */
|
||||
FROM @indexesToMaintains [ic] /* to create */
|
||||
JOIN @indexesToMaintains [ir] /* to rename */
|
||||
ON ic.[expectedIndexName_inp] = ir.[expectedIndexName_inp]
|
||||
WHERE [ic].[isToBeCreated_comp] = 1
|
||||
AND [ir].[isToBeRenamed_comp] = 1;
|
||||
|
||||
|
||||
/* Show the action matrix */
|
||||
IF @in_debug > 0
|
||||
BEGIN
|
||||
SELECT [itm].[isIndexFound_comp],
|
||||
[itm].[isToBeCreated_comp],
|
||||
[itm].[isToBeRenamed_comp],
|
||||
[itm].[isToBeDeleted_comp],
|
||||
[itm].[isToBeRecreated_comp],
|
||||
[itm].[statusMsg_internal],
|
||||
[itm].[IA_index_options],
|
||||
'....' AS separator,
|
||||
[itm].[isToBeDeleted_inp],
|
||||
[itm].[isToBeRecreated_inp],
|
||||
[itm].[indexName],
|
||||
[itm].[expectedIndexName_inp],
|
||||
[itm].[columnsName_inp],
|
||||
[itm].[actualColumns_internal],
|
||||
[itm].[includedColumns_inp],
|
||||
[itm].[actualIncludedColumns_internal]
|
||||
FROM @indexesToMaintains [itm]
|
||||
ORDER BY [itm].[isIndexFound_comp],
|
||||
[itm].[isToBeDeleted_inp],
|
||||
[itm].[columnsName_inp];
|
||||
END;
|
||||
|
||||
|
||||
/* Drop the indexe(s) that are to be deleted or recreated */
|
||||
SET @query = '';
|
||||
SELECT @query
|
||||
= @query + 'DROP INDEX ' + [itm].[indexName] + ' ON ' + [itm].[SchemaName] + '.' + [itm].[TableName] + ';'
|
||||
+ CHAR(13) + CHAR(10)
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE [itm].[isToBeDeleted_comp] = 1
|
||||
OR [itm].[isToBeRecreated_comp] = 1;
|
||||
|
||||
IF @outputStatement = 1
|
||||
BEGIN
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT '-- execute DROP INDEX';
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT @query;
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT CHAR(13) + CHAR(10);
|
||||
END;
|
||||
|
||||
IF @executeStatement = 1
|
||||
BEGIN
|
||||
EXECUTE (@query);
|
||||
END;
|
||||
|
||||
|
||||
/* rename existing indexe(s) */
|
||||
SET @query = '';
|
||||
SELECT @query
|
||||
= @query + 'EXEC sp_rename @objname =''' + [itm].[TableName] + '.' + [itm].[indexName] + ''', @newname = '''
|
||||
+ [itm].[expectedIndexName_inp] + ''';' + CHAR(13) + CHAR(10)
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE [itm].[isToBeRenamed_comp] = 1;
|
||||
|
||||
IF @outputStatement = 1
|
||||
BEGIN
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT '-- execute sp_rename';
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT @query;
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT CHAR(13) + CHAR(10);
|
||||
END;
|
||||
|
||||
IF @executeStatement = 1
|
||||
BEGIN
|
||||
EXECUTE (@query);
|
||||
END;
|
||||
|
||||
|
||||
/* create indexe(s) */
|
||||
SET @query = '';
|
||||
SELECT @query
|
||||
= @query + 'CREATE ' + CASE
|
||||
WHEN [itm].[isUnique_inp] = 1 THEN
|
||||
'UNIQUE '
|
||||
ELSE
|
||||
''
|
||||
END + CASE
|
||||
WHEN [itm].[isClustered_inp] = 1 THEN
|
||||
'CLUSTERED'
|
||||
ELSE
|
||||
'NONCLUSTERED'
|
||||
END + ' INDEX ' + [itm].[expectedIndexName_inp] + ' ON ' + [itm].[SchemaName]
|
||||
+ '.' + [itm].[TableName] + '(' + [itm].[columnsName_inp] + ')'
|
||||
+ CASE
|
||||
WHEN [itm].[includedColumns_inp] IS NOT NULL THEN
|
||||
' INCLUDE (' + [itm].[includedColumns_inp] + ')'
|
||||
ELSE
|
||||
''
|
||||
END + CHAR(13) + CHAR(10) + COALESCE('WITH(' + [itm].[IA_index_options] + ')' + CHAR(13) + CHAR(10), '')
|
||||
+ ';' + CHAR(13) + CHAR(10)
|
||||
FROM @indexesToMaintains [itm]
|
||||
WHERE (
|
||||
[itm].[isToBeCreated_comp] = 1
|
||||
OR [itm].[isToBeRecreated_comp] = 1
|
||||
);
|
||||
|
||||
IF @outputStatement = 1
|
||||
BEGIN
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT '-- execute CREATE INDEX';
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT @query;
|
||||
PRINT REPLICATE('-', 40);
|
||||
PRINT CHAR(13) + CHAR(10);
|
||||
END;
|
||||
|
||||
IF @executeStatement = 1
|
||||
BEGIN
|
||||
EXECUTE (@query);
|
||||
END;
|
||||
|
||||
/* record results in upd.IA_IndexesAlignementActions */
|
||||
UPDATE ia
|
||||
SET ia.[IA_executionDate] = CURRENT_TIMESTAMP,
|
||||
ia.[IA_foundIndexName] = ii.indexName,
|
||||
ia.[IA_wasIndexFound] = ii.isIndexFound_comp,
|
||||
ia.[IA_wasCreated] = ii.isToBeCreated_comp,
|
||||
ia.[IA_wasRenamed] = ii.isToBeRenamed_comp,
|
||||
ia.[IA_wasDeleted] = ii.isToBeDeleted_comp,
|
||||
ia.[IA_wasRecreated] = ii.isToBeRecreated_comp,
|
||||
ia.[IA_includedColumnsMatch] = ii.includedColumnsMatch_internal,
|
||||
ia.[IA_actualColumns] = ii.actualColumns_internal,
|
||||
ia.[IA_actualIncludedColumns] = ii.actualIncludedColumns_internal,
|
||||
ia.[IA_statusMsg] = ii.statusMsg_internal
|
||||
FROM [upd].[IA_IndexesAlignementActions] ia
|
||||
JOIN @indexesToMaintains ii
|
||||
ON ii.[IA_indexesAlignementActions] = ia.[IA_indexesAlignementActions_id]
|
||||
WHERE ia.[IA_executionDate] IS NULL;
|
||||
END;
|
||||
GO
|
||||
82
OCTPDBA-414 - proc to align indexes/table.sql
Normal file
82
OCTPDBA-414 - proc to align indexes/table.sql
Normal file
@@ -0,0 +1,82 @@
|
||||
USE Arizona
|
||||
|
||||
IF OBJECT_ID('upd.IA_IndexesAlignementActions') IS NOT NULL
|
||||
DROP TABLE upd.IA_IndexesAlignementActions;
|
||||
GO
|
||||
|
||||
CREATE TABLE upd.IA_IndexesAlignementActions(
|
||||
IA_indexesAlignementActions_id INT NOT NULL IDENTITY(1,1)
|
||||
,IA_executionDate DATETIME2(0) NULL /* The date and time the action was executed, null if the action is to be executed */
|
||||
,IA_schema_name VARCHAR(100) NOT NULL /* the schema the table is part of */
|
||||
,IA_table_name VARCHAR(100) NOT NULL /* On which table is the index, whithout the schema */
|
||||
,IA_columns_name VARCHAR(MAX) NOT NULL /* list all the columns of the index, in the correct orders */
|
||||
,IA_is_clustered BIT NOT NULL /* Is the indexe a clustered index ? */
|
||||
,IA_is_unique BIT NOT NULL /* Is the index unique ? */
|
||||
,IA_included_columns VARCHAR(MAX)NULL /* list all the included columns the index should have. */
|
||||
,IA_index_options VARCHAR(MAX) NULL /* Give here the index options if any. they will be applied on index creation but they are not part of the delta checks */
|
||||
,IA_is_to_be_deleted BIT NOT NULL /* must the script drop this index ? */
|
||||
,IA_is_to_be_recreated BIT NOT NULL /* must the script recreate this index ?
|
||||
If an existing index differs from the definition, it will be dropped and the correct one created.
|
||||
Use this only to force the re-creation even if the structure is identical */
|
||||
,IA_expected_index_name VARCHAR(500) NOT NULL /* the name the index should have, used to determine if a rename of the existing index should be done */
|
||||
|
||||
|
||||
/* everything below is a log of past changes */
|
||||
,[IA_foundIndexName] VARCHAR(MAX) NULL /* computed by the script. The index name on this system, as indexes name can be different accross systems*/
|
||||
,[IA_wasIndexFound] BIT NOT NULL /* computed by the script. set to 1 if the index is present on the server */
|
||||
CONSTRAINT DF_IA_wasIndexFound DEFAULT 0
|
||||
,[IA_wasCreated] BIT NULL /* computed by the script. does this index was created on the server ? */
|
||||
CONSTRAINT DF_IA_wasCreated DEFAULT 0
|
||||
,[IA_wasRenamed] BIT NULL /* computed by the script. does this index was renamed ? */
|
||||
CONSTRAINT DF_IA_wasRenamed DEFAULT 0
|
||||
,[IA_wasDeleted] BIT NULL /* computed by the script. does this index will be deleted ? */
|
||||
CONSTRAINT DF_IA_wasDeleted DEFAULT 0
|
||||
,[IA_wasRecreated] BIT NULL /* computed by the script. does this index will be re-created ? */
|
||||
CONSTRAINT DF_IA_wasRecreated DEFAULT 0
|
||||
,[IA_includedColumnsMatch] BIT NULL /* computed by the script. Are the expected and actual included columns identical ? */
|
||||
,[IA_actualColumns] VARCHAR(MAX) NULL /* the actual columns in the existing index */
|
||||
,[IA_actualIncludedColumns] VARCHAR(MAX) NULL /* the actual columns in the INCLUDE part of the index */
|
||||
,[IA_statusMsg] VARCHAR(MAX) NULL /* Message, used for debug */
|
||||
,CONSTRAINT PK_IA_IndexesAlignementActions PRIMARY KEY(IA_indexesAlignementActions_id)
|
||||
);
|
||||
ALTER TABLE upd.IA_IndexesAlignementActions ADD CONSTRAINT DF_IA_is_clustered DEFAULT 0 FOR IA_is_clustered;
|
||||
ALTER TABLE upd.IA_IndexesAlignementActions ADD CONSTRAINT DF_IA_is_unique DEFAULT 0 FOR IA_is_unique;
|
||||
ALTER TABLE upd.IA_IndexesAlignementActions ADD CONSTRAINT DF_IA_is_to_be_deleted DEFAULT 0 FOR IA_is_to_be_deleted;
|
||||
ALTER TABLE upd.IA_IndexesAlignementActions ADD CONSTRAINT DF_IA_is_to_be_recreated DEFAULT 0 FOR IA_is_to_be_recreated;
|
||||
|
||||
CREATE UNIQUE NONCLUSTERED INDEX NCUIX_IA_IndexesAlignementActions_index_name ON upd.IA_IndexesAlignementActions(IA_expected_index_name);
|
||||
GO
|
||||
|
||||
INSERT INTO upd.IA_IndexesAlignementActions (
|
||||
IA_columns_name,
|
||||
IA_is_to_be_deleted,
|
||||
IA_is_to_be_recreated,
|
||||
IA_expected_index_name,
|
||||
IA_included_columns,
|
||||
[IA_schema_name],
|
||||
[IA_table_name],
|
||||
[IA_is_clustered],
|
||||
[IA_is_unique]
|
||||
)
|
||||
/* indexe(s) we do want */
|
||||
VALUES('Entry_id',0,0,'PK_Entry_id', NULL,'dbo','entry',0,0)
|
||||
,('ET_batch_run',0,0,'NCIX_Entry_COL_ET_batch_run',NULL,'dbo','entry',0,0)
|
||||
,('ET_accounting_period',0,0,'NCIX_Entry_COL_ET_accounting_period','Entry_ID','dbo','entry',0,0)
|
||||
,('ET_document_header',0,0,'NCIX_Entry_COL_ET_document_header','ET_debit_currency_amount, ET_credit_currency_amount','dbo','entry',0,0)
|
||||
,('ET_account, ET_document_header',0,0,'NCIX_Entry_COL_ET_account','Entry_ID','dbo','entry',0,0)
|
||||
,('ET_reconciliation_status, ET_account, ET_document_header',0,0,'NCIX_Entry_COL_ET_reconciliation_status','ET_debit_base_amount, ET_credit_base_amount, ET_reconciliation_base_amount','dbo','entry',0,0)
|
||||
,('ET_predefined_entry',0,0,'NCIX_Entry_COL_ET_predefined_entry',NULL,'dbo','entry',0,0)
|
||||
,('ET_entry_address',0,0,'NCIX_Entry_COL_ET_entry_address',NULL,'dbo','entry',0,0)
|
||||
,('ET_currency',0,0,'NCIX_Entry_COL_ET_currency',NULL,'dbo','entry',0,0)
|
||||
|
||||
/* indexe(s) used in central, even if not in pharmacies*/
|
||||
,('ET_entry_type',0,0,'NCIX_Entry_COL_ET_entry_type',NULL,'dbo','entry',0,0)
|
||||
|
||||
/* indexe(s) we really want to drop*/
|
||||
,('ET_master_ID',1,0,'NCIX_Entry_COL_ET_master_ID',NULL,'dbo','entry',0,0)
|
||||
,('ET_bmc_user_profile',1,0,'NCIX_Entry_COL_ET_bmc_user_profile',NULL,'dbo','entry',0,0)
|
||||
,('ET_sales_tax_code',1,0,'NCIX_Entry_COL_ET_sales_tax_code',NULL,'dbo','entry',0,0)
|
||||
,('ET_APS_TS', 1, 0, 'NCIX_Entry_COL_ET_APS_TS',NULL,'dbo','entry',0,0)
|
||||
|
||||
;
|
||||
|
||||
156
OCTPDBA-414 - proc to align indexes/test.sql
Normal file
156
OCTPDBA-414 - proc to align indexes/test.sql
Normal file
@@ -0,0 +1,156 @@
|
||||
USE Arizona;
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
SET XACT_ABORT ON;
|
||||
|
||||
|
||||
INSERT INTO upd.IA_IndexesAlignementActions
|
||||
(
|
||||
IA_executionDate,
|
||||
IA_schema_name,
|
||||
IA_table_name,
|
||||
IA_columns_name,
|
||||
IA_is_clustered,
|
||||
IA_is_unique,
|
||||
IA_included_columns,
|
||||
IA_is_to_be_deleted,
|
||||
IA_is_to_be_recreated,
|
||||
IA_expected_index_name,
|
||||
IA_foundIndexName,
|
||||
IA_wasIndexFound,
|
||||
IA_wasCreated,
|
||||
IA_wasRenamed,
|
||||
IA_wasDeleted,
|
||||
IA_wasRecreated,
|
||||
IA_includedColumnsMatch,
|
||||
IA_actualColumns,
|
||||
IA_actualIncludedColumns,
|
||||
IA_statusMsg,
|
||||
IA_index_options
|
||||
)
|
||||
SELECT
|
||||
NULL AS IA_executionDate,
|
||||
'dbo' AS IA_schema_name,
|
||||
'Criteria' AS IA_table_name,
|
||||
'CR_code, CR_criteria_type' AS IA_columns_name,
|
||||
0 AS IA_is_clustered,
|
||||
1 AS IA_is_unique,
|
||||
NULL AS IA_included_columns,
|
||||
0 AS IA_is_to_be_deleted,
|
||||
0 AS IA_is_to_be_recreated,
|
||||
'NCIX_Criteria_COL_CR_code' AS IA_expected_index_name,
|
||||
NULL AS IA_foundIndexName,
|
||||
0 AS IA_wasIndexFound,
|
||||
0 AS IA_wasCreated,
|
||||
0 AS IA_wasRenamed,
|
||||
0 AS IA_wasDeleted,
|
||||
0 AS IA_wasRecreated,
|
||||
NULL AS IA_includedColumnsMatch,
|
||||
NULL AS IA_actualColumns,
|
||||
NULL AS IA_actualIncludedColumns,
|
||||
NULL AS IA_statusMsg ,
|
||||
NULL AS IA_index_options
|
||||
UNION
|
||||
SELECT
|
||||
NULL AS IA_executionDate,
|
||||
'dbo' AS IA_schema_name,
|
||||
'Criteria' AS IA_table_name,
|
||||
'CR_criteria_type' AS IA_columns_name,
|
||||
0 AS IA_is_clustered,
|
||||
0 AS IA_is_unique,
|
||||
NULL AS IA_included_columns,
|
||||
0 AS IA_is_to_be_deleted,
|
||||
0 AS IA_is_to_be_recreated,
|
||||
'NCIX_Criteria_COL_CR_criteria_type' AS IA_expected_index_name,
|
||||
NULL AS IA_foundIndexName,
|
||||
0 AS IA_wasIndexFound,
|
||||
0 AS IA_wasCreated,
|
||||
0 AS IA_wasRenamed,
|
||||
0 AS IA_wasDeleted,
|
||||
0 AS IA_wasRecreated,
|
||||
NULL AS IA_includedColumnsMatch,
|
||||
NULL AS IA_actualColumns,
|
||||
NULL AS IA_actualIncludedColumns,
|
||||
NULL AS IA_statusMsg ,
|
||||
NULL AS IA_index_options
|
||||
UNION
|
||||
SELECT
|
||||
NULL AS IA_executionDate,
|
||||
'dbo' AS IA_schema_name,
|
||||
'Criteria' AS IA_table_name,
|
||||
'CR_master_ID' AS IA_columns_name,
|
||||
0 AS IA_is_clustered,
|
||||
0 AS IA_is_unique,
|
||||
NULL AS IA_included_columns,
|
||||
0 AS IA_is_to_be_deleted,
|
||||
01 AS IA_is_to_be_recreated,
|
||||
'NCIX_Criteria_COL_CR_master_ID' AS IA_expected_index_name,
|
||||
NULL AS IA_foundIndexName,
|
||||
0 AS IA_wasIndexFound,
|
||||
0 AS IA_wasCreated,
|
||||
0 AS IA_wasRenamed,
|
||||
0 AS IA_wasDeleted,
|
||||
0 AS IA_wasRecreated,
|
||||
NULL AS IA_includedColumnsMatch,
|
||||
NULL AS IA_actualColumns,
|
||||
NULL AS IA_actualIncludedColumns,
|
||||
NULL AS IA_statusMsg,
|
||||
NULL AS IA_index_options
|
||||
UNION
|
||||
SELECT
|
||||
NULL AS IA_executionDate,
|
||||
'dbo' AS IA_schema_name,
|
||||
'Criteria' AS IA_table_name,
|
||||
'CR_VGUID' AS IA_columns_name,
|
||||
0 AS IA_is_clustered,
|
||||
0 AS IA_is_unique,
|
||||
NULL AS IA_included_columns,
|
||||
0 AS IA_is_to_be_deleted,
|
||||
0 AS IA_is_to_be_recreated,
|
||||
'NCIX_Criteria_COL_CR_VGUID' AS IA_expected_index_name,
|
||||
NULL AS IA_foundIndexName,
|
||||
0 AS IA_wasIndexFound,
|
||||
0 AS IA_wasCreated,
|
||||
0 AS IA_wasRenamed,
|
||||
0 AS IA_wasDeleted,
|
||||
0 AS IA_wasRecreated,
|
||||
NULL AS IA_includedColumnsMatch,
|
||||
NULL AS IA_actualColumns,
|
||||
NULL AS IA_actualIncludedColumns,
|
||||
NULL AS IA_statusMsg ,
|
||||
NULL AS IA_index_options
|
||||
UNION
|
||||
SELECT
|
||||
NULL AS IA_executionDate,
|
||||
'dbo' AS IA_schema_name,
|
||||
'Criteria' AS IA_table_name,
|
||||
'Criteria_ID' AS IA_columns_name,
|
||||
1 AS IA_is_clustered,
|
||||
1 AS IA_is_unique,
|
||||
NULL AS IA_included_columns,
|
||||
0 AS IA_is_to_be_deleted,
|
||||
0 AS IA_is_to_be_recreated,
|
||||
'PK_Criteria_ID' AS IA_expected_index_name,
|
||||
NULL AS IA_foundIndexName,
|
||||
0 AS IA_wasIndexFound,
|
||||
0 AS IA_wasCreated,
|
||||
0 AS IA_wasRenamed,
|
||||
0 AS IA_wasDeleted,
|
||||
0 AS IA_wasRecreated,
|
||||
NULL AS IA_includedColumnsMatch,
|
||||
NULL AS IA_actualColumns,
|
||||
NULL AS IA_actualIncludedColumns,
|
||||
NULL AS IA_statusMsg ,
|
||||
NULL AS IA_index_options
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
EXEC [upd].[alignIndexes] @in_debug = 01, -- int
|
||||
@in_dropUnreferencedIndexes = NULL; -- bit
|
||||
|
||||
SELECT *
|
||||
FROM upd.IA_IndexesAlignementActions;
|
||||
|
||||
ROLLBACK TRANSACTION;
|
||||
Reference in New Issue
Block a user