How to check if a table has columnstore index? - sql-server

I need to make some mechanism that checks if a table X is columnstored or not and if it is not to convert it.
I am aware that to convert a table X for example to clustered columnstore index we can use the following code:
CREATE CLUSTERED COLUMNSTORE INDEX MyColumnStoreIndex
ON Table_X
I would like to make a query that checks if a table contains columnstore index.
Thanks in advance.

You can query sys.indexes and check the type and type_desc columns. According to the documentation values 5 and 6 hold information whether an index is clustered or nonclustered columnstore:
select *
from sys.indexes
where type in (5, 6)

you can query the sys.indexes as mentioned in Rigerta's answer.
To also get the tablename that belongs to found indexes you can do following query
select i.name as indexname,
t.name as tablename
from sys.indexes i
join sys.tables t on i.object_id = t.object_id
where i.type in (5, 6)

Related

How does one Remove a Partition from a Table?

I have managed to add a Partition to a Table (Logs) but needed to create a Rollback script in case it needs to be removed. Unfortunately, this has now failed and Logs now has no primary key as a result of failing part-way through the rollback script and I have no way to add it back as I get the error...
Column 'SuperLogId' is partitioning column of the index 'PK__Logs__0E6B88F2'. Partition columns for a unique index must be a subset of the index key.
when trying to run this:
ALTER TABLE dbo.Logs
ADD PRIMARY KEY CLUSTERED (Id ASC)
So I tried following this guide (https://www.patrickkeisler.com/2013/01/how-to-remove-undo-table-partitioning.html) and ended up having to write this to generate a script to merge all my dynamically-created partitions.
DECLARE #partitionsTable dbo.NVarCharCollectionTableType --User-defined table type to hold a collection of NVarChars.
INSERT INTO #partitionsTable
SELECT CONCAT('ALTER PARTITION FUNCTION Logs_SuperLogId_PartitionFunction() MERGE RANGE (', CONVERT(NVARCHAR, [Value]), ')')
FROM SYS.PARTITION_SCHEMES
INNER JOIN SYS.PARTITION_FUNCTIONS ON PARTITION_FUNCTIONS.FUNCTION_ID = PARTITION_SCHEMES.FUNCTION_ID
INNER JOIN SYS.PARTITION_RANGE_VALUES ON PARTITION_RANGE_VALUES.FUNCTION_ID = PARTITION_FUNCTIONS.FUNCTION_ID
WHERE PARTITION_SCHEMES.Name = 'Logs_SuperLogId_PartitionScheme'
AND PARTITION_FUNCTIONS.Name = 'Logs_SuperLogId_PartitionFunction'
ORDER BY [Value] ASC
DECLARE #statement NVARCHAR(MAX)
SELECT #statement =
CASE
WHEN #statement IS NULL
THEN CAST([Text] AS NVARCHAR(MAX))
ELSE CONCAT(#statement, '; ', [Text])
END
FROM #partitionsTable
ORDER BY [Text] ASC
SELECT #statement
EXECUTE SP_EXECUTESQL #statement
ALTER PARTITION SCHEME Logs_SuperLogId_PartitionScheme NEXT USED [PRIMARY]
The guide suggested this would help somehow but it didn't! I still get the same error when trying to re-add the Primary Key and still get these errors for trying to drop the Partition Function and Partition Scheme!
DROP PARTITION SCHEME Logs_SuperLogId_PartitionScheme
The partition scheme "Logs_SuperLogId_PartitionScheme" is currently being used to partition one or more tables.
DROP PARTITION FUNCTION CatLogs_CatSessionLogId_PartitionFunction
Partition function 'Logs_SuperLogId_PartitionFunction' is being used by one or more partition schemes.
How is my Partition Scheme still being used? Why can't I just get rid of it and it be not used anymore? I just want to de-partition my Logs table and re-add its original clustered primary key (which I had to previously remove and replace with a non-clustered primary key to make SuperLogId have a clustered index on it so it could be partitioned upon).
Update:
I was able to use the following hack to get the Partition removed from my table but I still can't drop the Partition Scheme or Function.
--HACK: Dummy Index to disassociate the table from the partitioning scheme.
CREATE CLUSTERED INDEX IX_Logs_Id ON dbo.Logs(Id) ON [Primary]
--Now that the table has been disassociated with the partition, this dummy index can be dropped.
DROP INDEX IX_Logs_Id ON dbo.Logs
I have since ran this script to find out which tables are using any Partitions in my database and it returns nothing, as expected.
SELECT DISTINCT TABLES.NAME
FROM SYS.PARTITIONS
INNER JOIN SYS.TABLES ON PARTITIONS.OBJECT_ID = TABLES.OBJECT_ID
WHERE PARTITIONS.PARTITION_NUMBER <> 1
This allowed me to re-add the Primary key but I still get the The partition scheme "Logs_SuperLogId_PartitionScheme" is currently being used... error when trying to drop the Partition Scheme.
Based on the Microsoft documentation (https://learn.microsoft.com/en-us/sql/t-sql/statements/drop-partition-scheme-transact-sql?view=sql-server-2017), the Partition Scheme should be droppable if there are no tables or indices references it. Therefore I subsequently also ran this script to check for an index using it...
SELECT DISTINCT indexes.NAME
FROM SYS.PARTITIONS
INNER JOIN SYS.indexes ON indexes.index_id = partitions.index_id
WHERE PARTITIONS.PARTITION_NUMBER <> 1
...And it returned nothing! So what on earth is using my Partition Scheme?!
I was able to remove the Partition from its table with the following code.
--HACK: Dummy Index to disassociate the table from the partitioning scheme.
CREATE CLUSTERED INDEX IX_Logs_Id ON dbo.Logs(Id) ON [Primary]
--Now that the table has been disassociated with the partition, this dummy index can be dropped.
DROP INDEX IX_Logs_Id ON dbo.Logs
Then, using the following script, found out that two indices were still holding onto the Partition Scheme.
SELECT SCHEMA_NAME(B.SCHEMA_ID) SCHEMANAME, B.NAME TABLENAME, C.INDEX_ID, C.NAME INDEXNAME, C.TYPE_DESC,
A.PARTITION_NUMBER, D.NAME DATASPACENAME, F.NAME SCHEMADATASPACENAME,
H.VALUE DATARANGEVALUE, A.ROWS,
J.IN_ROW_RESERVED_PAGE_COUNT, J.LOB_RESERVED_PAGE_COUNT,
J.IN_ROW_RESERVED_PAGE_COUNT+J.LOB_RESERVED_PAGE_COUNT TOTALPAGECOUNT,
I.LOCATION
FROM SYS.PARTITIONS A
JOIN SYS.TABLES B ON A.OBJECT_ID = B.OBJECT_ID
JOIN SYS.INDEXES C ON A.OBJECT_ID = C.OBJECT_ID AND A.INDEX_ID = C.INDEX_ID
JOIN SYS.DATA_SPACES D ON C.DATA_SPACE_ID = D.DATA_SPACE_ID
LEFT JOIN SYS.DESTINATION_DATA_SPACES E ON E.PARTITION_SCHEME_ID = D.DATA_SPACE_ID AND A.PARTITION_NUMBER = E.DESTINATION_ID
LEFT JOIN SYS.DATA_SPACES F ON E.DATA_SPACE_ID = F.DATA_SPACE_ID
LEFT JOIN SYS.PARTITION_SCHEMES G ON D.NAME = G.NAME
LEFT JOIN SYS.PARTITION_RANGE_VALUES H ON G.FUNCTION_ID = H.FUNCTION_ID AND H.BOUNDARY_ID = A.PARTITION_NUMBER
LEFT JOIN (SELECT DISTINCT DATA_SPACE_ID, LEFT(PHYSICAL_NAME, 1) LOCATION FROM SYS.DATABASE_FILES) I ON I.DATA_SPACE_ID = ISNULL(F.DATA_SPACE_ID, D.DATA_SPACE_ID)
LEFT JOIN SYS.DM_DB_PARTITION_STATS J ON J.OBJECT_ID = A.OBJECT_ID AND J.INDEX_ID = A.INDEX_ID AND J.PARTITION_NUMBER = A.PARTITION_NUMBER
ORDER BY 1, 2, 3, A.PARTITION_NUMBER
All I had to do was drop the two indices referencing the Partition Scheme then that allowed me to drop the Partition Scheme, then Partition Function.
Taking the SSMS UI route (rather than figuring out all the DDL script), R-click the partitioned table in the Object Explorer, Design, R-click design area, Indexes, select each partitioned index, expand Data Space Specification, select Data Space Type dropdown and select "Filegroup." Your index will be off the partition and back on PRIMARY.
However, you're not done. Hit F4 to bring up table properties on the right, and do the same process. Remember to Save when you're done. Freedom!

How to identify all the tables that have (or don't have) a unique index?

What is the most efficient way in SQL Server to identify all tables that have a unique index?
This has been addressed elsewhere for Oracle: https://stackoverflow.com/a/28740458/3112914
My end goal is to identify tables in a database that can not be compared using SSDT Data Compare tool. For that tool to work "Tables must have the same primary key, unique index, or unique constraint." I can identify those with primary key or unique constraint using OBJECTPROPERTY, e.g.
SELECT
SCHEMA_NAME(schema_id) AS SchemaName,
name AS TableName,
OBJECTPROPERTY(OBJECT_ID,'TableHasPrimaryKey') AS HasPrimaryKey,
OBJECTPROPERTY(OBJECT_ID,'TableHasUniqueCnst') AS HasUniqueConstraint
FROM
sys.tables
There is an IsIndexed property but that doesn't say that is a unique index. https://learn.microsoft.com/en-us/sql/t-sql/functions/objectproperty-transact-sql?view=sql-server-2017
If you want to list all the tables that have a unique index you can join to sys.indexes and filter using column is_unique.
e.g.
-- list of tables that have a unique index
SELECT SCHEMA_NAME(schema_id) AS SchemaName,
name AS TableName
FROM
sys.tables
WHERE EXISTS (SELECT *
FROM sys.indexes i
WHERE i.object_id = tables.object_id AND is_unique = 1)
If you want to extend the show every table, along with a value indicating whether or not it has a unique index (ie extend the start you had above), you can wrap that EXISTS statement in an IIF or CASE, like this :
SELECT SCHEMA_NAME(schema_id) AS SchemaName,
name AS TableName,
OBJECTPROPERTY(OBJECT_ID, 'TableHasPrimaryKey') AS HasPrimaryKey,
OBJECTPROPERTY(OBJECT_ID, 'TableHasUniqueCnst') AS HasUniqueConstraint,
CASE
WHEN EXISTS (
SELECT *
FROM sys.indexes i
WHERE i.object_id = tables.object_id
AND is_unique = 1
)
THEN 1
ELSE 0
END AS HasUniqueIndex
FROM sys.tables

SQL Server 2012: Constraint has NULL for name. How can I drop this?

I am not sure how this happened, but I have a PRIMARY KEY constraint on one of my tables and the name is NULL. I discovered it because I had to drop/recreate the table, and when I tried to add the PRIMARY KEY, the system responded that the constraint already existed.
I executed the following:
SELECT i.object_id, i.name, i.type_desc
FROM sys.indexes i
INNER JOIN sys.tables t ON i.object_id = t.object_id
AND t.name = N'Organization'
and the result is:
object_id name type_desc
1570377655 NULL HEAP
1570377655 IX_Organization_OwnedByOrganizationId NONCLUSTERED
I tried dropping and recreating the table several times and each time the index is there. How can I drop the constraint?
You can try to find the index you are trying to add using the following query:
SELECT [Table] = t.[name]
, [Index] = i.[name]
, i.*
FROM sys.indexes i
INNER JOIN sys.tables t
ON t.[object_id] = i.[object_id]
Martin has the right answer to index you find with the NULL name.

list of tables without indexes in sql 2008

How do I list tables without indexes in my SQL 2008 database?
Edit
I want the Schema name and the Table name.
This should cover what your looking for. i.e. tables that are heaps (no clustered index) and do not have any non-clustered indexes. It uses the new sys. table objects used in 2005/2008.
in addition, you probably want to look for tables that do have a clustered index, but have no nonclustered indexes (this is the 2nd part of the statement which I've left commented out.
SELECT
schemaname = OBJECT_SCHEMA_NAME(o.object_id)
,tablename = o.NAME
FROM sys.objects o
INNER JOIN sys.indexes i ON i.OBJECT_ID = o.OBJECT_ID
-- tables that are heaps without any nonclustered indexes
WHERE (
o.type = 'U'
AND o.OBJECT_ID NOT IN (
SELECT OBJECT_ID
FROM sys.indexes
WHERE index_id > 0
)
)
-- OR
-- table that have a clustered index without any nonclustered indexes
--(o.type='U'
-- AND o.OBJECT_ID NOT IN (
-- SELECT OBJECT_ID
-- FROM sys.indexes
-- WHERE index_id>1))
Here's an example:
select SCHEMA_NAME(schema_id), name from sys.tables
where OBJECTPROPERTY(object_id, 'IsIndexed')= 0
In addition to #Philip Fourie's suggestion you might want to think about which indexes to create.
Once you have been accessing your data, SQL Server 2008 keeps track of places where it thinks indexes will be helpful (it refers to these as "missing indexes." There are a hand full of new Dynamic Managed Views which can show these missing indexes and some info about them.
From MSSQlTips:
sys.dm_db_missing_index_details - Returns detailed information about a missing index
sys.dm_db_missing_index_group_stats - Returns summary information about missing index groups
sys.dm_db_missing_index_groups - Returns information about a specific group of missing indexes
sys.dm_db_missing_index_columns(index_handle) - Returns information about the database table columns that are missing for an index. This is a function and requires the index_handle to be passed.
select shema = s.name, table_name = o.name
from sys.objects o
join sys.schemas s on o.schema_id = s.schema_id
where type = 'U'
and not exists (select i.index_id
from sys.indexes i
where i.type <> 0 --ignore default heap index row
and o.object_id = i.object_id )
Edit:
I have updated the SQL to include the Schema name as requested. (Note I had to sys.objects instead of sysobjects to cater for schemas that were introduced in SQL 2005)
The catalog tables are documented in the SQL Server documentation, see this link.
This FAQ contains more samples and might also be useful.
Note that these are system tables and can change between SQL server versions, where possible rather use the system table-independent views called Information Schema Views.
This code gives all the details about the indexes for all the tables:
SELECT
sch.name AS [Schema],
obj.name AS TableName,
indx.name AS IndexName,
CASE
WHEN indx.type_desc = 'HEAP' THEN 'N/A'
ELSE indx.type_desc
END AS IndexType
FROM sys.objects obj
JOIN sys.indexes indx ON indx.object_id = obj.object_id
JOIN sys.schemas AS sch ON sch.schema_id = obj.schema_id
WHERE
obj.type = 'U'
ORDER BY
obj.name

Identifying indentity column?

I have found that how to determine what columns are primary key column of a given table by using this query:
SELECT CONSTRAINT_NAME, COLUMN_NAME
FROM
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
WHERE TABLE_NAME='tablename_here' AND
CONSTRAINT_NAME LIKE 'PK_%'
I can find , what the identity seed and increment is by using this query:
SELECT IDENT_SEED('tablename_here'), IDENT_INCR('tablename_here')
I cant use the constraint information, because a primary key constraint can be across multiple columns. And i cant seem to find any Transact SQL function to give my the identity information.
Can anybody help me to understand how to find the identity information?
I am using SQL Server 2000.
To find the IDENTITY column in a given table you can use this:
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='tablename_here'
AND COLUMNPROPERTY(OBJECT_ID('tablename_here'),COLUMN_NAME,'IsIdentity') = 1
You can use the COLUMNPROPERTY function to check whether a column uses the identity property.
SELECT sys.tables.name, sys.columns.name
FROM sys.tables
INNER JOIN sys.columns
ON sys.tables.object_id = sys.columns.object_id
WHERE is_identity = 1
AND sys.tables.name = 'MyTable'

Resources