This past week I needed to run some queries on production to verify there were indexes added on a table. There were several scripts that needed to be run and the last one was the addition of the indexes. The query given to me was something like the following
SELECT * FROM LinkedServerName.DatabaseName.sys.indexes WHERE object_id =(OBJECT_ID('TableName'))
So I ran the query..nothing. Aha maybe they are still running the scripts before that, setting up replication, snapshotting the table etc etc. I will check again in a bit I thought.
Then I checked 2 more times nothing. So I then contacted them and asked if they ran everything..yes they said and no errors. Mmm, okay..what could be wrong. The only way I can access this server is through a linked server call. I decided to look at the query again.... bingo.. I see what the problem is.....
Let's take a look. First create the following database with 2 tables and 2 indexes on the Test table
CREATE DATABASE Test1 GO USE Test1 GO CREATE TABLE Foo(ID int) GO CREATE TABLE Test(ID int, ID2 int, ID3 int) GO CREATE INDEX ix_Test on Test(ID) CREATE INDEX ix_Test2 on Test(ID2)
Now if you run the following query against the sys.indexes object catalog view
SELECT FROM sys.indexes WHERE object_id = OBJECT_ID('Test')
You will get back the following information
object_id | name | index_id | type | type_desc |
901578250 | NULL | 0 | 0 | HEAP |
901578250 | ix_Test | 2 | 2 | NONCLUSTERED |
901578250 | ix_Test2 | 3 | 2 | NONCLUSTERED |
As you can see we have information about our two indexes and the table itself, since there is no clustered index on this table, we get a row back that shows that the table is a heap
Now let us connect to another database on the same server, in this case we will use the tempdb database
Create a table with the same name
Create a table with the same name
USE tempdb GO CREATE TABLE Test(foo int) GO
Now run the same query again but point to the Test1 database
SELECT * FROM Test1.sys.indexes WHERE object_id = OBJECT_ID('Test')
And you get nothing back. What does the OBJECT_ID() function return?
SELECT OBJECT_ID('Test')
For me it returns the number 965578478. The problem is that that object_id is the id for that object in the tempdb database, not for the one in the Test1 database
So what can you do? There are two ways to do this
One way is to join sys.indexes with the sys.tables object catalog view
Here is what the query looks like
SELECT i.* FROM Test1.sys.indexes i JOIN Test1.sys.tables t ON i.object_id = t.object_id WHERE t.name = 'Test'
Running the query like that displays the correct information
object_id | name | index_id | type | type_desc |
901578250 | NULL | 0 | 0 | HEAP |
901578250 | ix_Test | 2 | 2 | NONCLUSTERED |
901578250 | ix_Test2 | 3 | 2 | NONCLUSTERED |
If you want to use this against a linked server, use 4 part notation, just prefix Test1.sys with the linked server name, I used LinkedServerName as an example
SELECT i.* FROM LinkedServerName.Test1.sys.indexes i JOIN LinkedServerName.Test1.sys.tables t ON i.object_id = t.object_idWHERE t.name = 'Test'
That query with the join between sys.indexes and sys.tables can be used for a linked server as well as a different database on the same instance, if you just have to go to another database like we have done before, you can simplify it like this
SELECT * FROM Test1.sys.indexes WHERE object_id = OBJECT_ID('Test1.dbo.Test')
Basically, you pass in the database name, schema name and object name to the OBJECT_ID() function
That's all for today..