How to get column names from a query in SQL Server - sql

Using SQL Server.
I have a very extensive query, with a lot of aliasing, etc...
Is there a way, using just SQL (stored proc is fine, but not PHP, etc), to get a list of all column names from this query? (I realize I will have to probably embed my query inside of this solution but that is fine. Just a temporary measure.)
Thanks!

If you're using SQL Server 2012 or later you can take advantage of sys.dm_exec_describe_first_result_set
SELECT name
FROM
sys.dm_exec_describe_first_result_set
('Your Query Here', NULL, 0) ;
DEMO

There are various ways that you can get the columns out of the query, such as:
select top 0 s.*
from (<your query here>) s;
Then you can parse the results.
However, I have found another approach useful. Create either a view or a table using the same logic:
select top 0 s.*
into _TempTableForColumns
from (<your query here>) s;
Then use information_schema (or the system tables if you prefer):
select *
from information_schema.columns
where table_name = '_TempTableForColumns' and schema_name = 'dbo';
drop table _TempTableForColumns;
The advantage of this approach is that you can get type information along with the column names. But the engine still has to run the query and that might take time even though no rows are returned. Although the column names and types are available after compiling, I am not aware of a way to get them without also executing the query.

After SQL Server 2008
select *
from sys.columns c
inner join sys.objects o on c.object_id = o.object_id
where o.name = 'TableName'
Before
select *
from syscolumns c
inner join sysobjects o on c.id = o.id
where o.name = 'TableName'

Related

Get column differences between 2 databases (SQL Server)

I've got 2 databases almost identical to one another. However, it seems that for some tables in the new database, they are missing columns that are in the old database.
What would be the best way to see the differences between columns in tables between 2 databases? Specifically, I need to see what columns AREN'T in the new database that ARE in the old one.
I've tried looking this up but most things I found were either not what I needed or looking at "records".
You can query the columns from your db using the sys tables and compare the result sets. This script assumes your old db has all the columns you want.
;WITH old_db_columns AS (
SELECT c.object_id, c.column_id, c.name AS column_name, t.name AS table_name
FROM old_db.sys.tables t
INNER JOIN old_db.sys.columns c
ON t.object_id = c.object_id
)
, new_db_columns AS (
SELECT c.object_id, c.column_id, c.name AS column_name, t.name AS table_name
FROM new_db.sys.tables t
INNER JOIN new_db.sys.columns c
ON t.object_id = c.object_id
)
SELECT *
FROM old_db_columns o
WHERE NOT EXISTS (
SELECT 1
FROM new_db_columns n
WHERE n.table_name = o.table_name
AND n.column_name= o.column_name)
You may use SQL Compare and SQL Data Compare, tools by Red Gate, to compare and sync databases schema and data.
You can generate the create statement of the tables and you can compare them with using any diff tool.
Check out that video: VS Comparision
Visual Studio has built in functionality that you are able to do data compares, schema compares and it will generate the differences for you in a script if you need to recitfy the variances.

How to search for a specific string occurrence in stored procedures

I have a query that selects particular stored procedures, triggers and functions in my SQL database. I have retrieved 86 in total.
I need to find which of these are using a certain string inside.
This string is a name of a table.
I do not want to open each of these individually and search for it.
I'm thinking of having a script that looks inside of these and find what I need.
What I think I might need is something like from tableName or inner join on tableName or join on tableName and etc
What is a good way to do it in SQL
Thank you
To search one SQL Server database for a specific piece of text in a stored procedure you could do this:
DECLARE #SearchText VARCHAR(100) = 'TableXYZ';
SELECT DISTINCT
o.name,
o.type_desc
FROM
sys.sql_modules m
INNER JOIN sys.objects o ON m.object_id = o.object_id
WHERE
m.[definition] Like '%' + #SearchText + '%';
Obviously this is a bit of a hack and won't work out if your table name is called something daft like "SELECT" as that will just cause loads of false-positive results.
One alternative is to use the sys.dm_sql_referencing_entities system table, but my experience with this is that it can't be trusted. In general dependencies don't work very well with SQL Server due to some poor design decisions, e.g. deferred name resolution.
Microsoft SQL would cover Access, Sybase and SQL Server (and possibly more) .... But I suspect you are using SQL Server, as such I would suggest sys.dm_sql_referencing_entities rather than searching a definition for a particular string -
SELECT r.* , o.type_desc, m.definition
FROM sys.dm_sql_referencing_entities('dbo.TableName', 'OBJECT') AS r
INNER JOIN sys.all_objects AS o
ON o.[object_id] = r.referencing_id
INNER JOIN sys.sql_modules AS m
ON m.[object_id] = o.[object_id];
Here is a simple and easy to use Sql query
SELECT name
FROM sys.procedures
WHERE Object_definition(object_id) LIKE '%strHell%'
And here's a link for more info

Finding Indexes For A Table in Sybase

I am currently working in an environment where I am made double blind.
I have to email any queries I need to run to a employee of the client
That employee runs them in a SAS client, with an odbc connection to SyBase
I need to find out how to ascertain exactly what indexes exist on a specific table. I would use sp_helpindex, but apparently it doesn't exist on their instance of SyBase.
We believe that it is SyBase 12, but again I can't be certain of anything.
Does anyone have SQL for...
- Confirming exactly what version of SyBase we're working on?
- The details of all indexes that exist for a given table?
Most Sybase products have a -v command line argument to tell the version with or without the engine running.
To find the indexes on any table enter the following, where my_table is your table's name:
select i.name
from sysindexes i, sysobjects o
where o.name = 'my_table'
and o.id = i.id
To "Confirming exactly what version of SyBase we're working on?"
Why not use:
select ##version
Sybase website is down (at least here), but it would be something like:
IQ SHOW INDEXSET INDEXES
or
IQ SHOW INDEXSET FOR indexset
where indexset is tablename because every table has a indexset assigned with the same name.
If you have access to sybase website possibly you can go further :)
You can use this query:
select i.name
from sysindexes i, sysobjects o
where o.name = 'table_name' and i.indid >=1
and o.id = i.id
Find Indexes on multiple tables, not like image indexes
select name = o.name,iname = i.name from sysindexes i, sysobjects o where o.name in ('table1','table2','table3') and i.name not like 't%' and i.indid >=1 and o.id = i.id
For sybase version:
select ##version
in Sybase version SAP IQ/16, you can get list of indexes with following (table name my_table is case sensitive:
select *
from sys.sysindexes
where tname = 'my_table';
select * from sys.sysindexes where tname='Your Table name'
Try the above code, it worked for me.

I have a field name used in a SQL Server DB - how can I find where it is used?

I have a field name used in a SQL Server DB - I do not know if it is a table field or a stored procedure parameter. Is there a query I can run against the DB to find candidate fields in tables and stored procedures?
Depends on which version of sql server you are using:
For 2000, use syscolumns:
select object_name(select object_name(id)
from syscolumns
where name = 'ID'
For 2005+ use sys.columns:
select object_name(object_id)
from sys.columns
where name = 'ID'
The use of the object_name() function negates the need for an inner join on the objects table.
If it's SQL Server 2005 or 2008 you can use the INFORMATION_SCHEMA views.
http://msdn.microsoft.com/en-us/library/ms186778.aspx
SQL statement like this will find what you're looking for:
select * from information_schema.parameters where parameter_name like '%field%'
select * from information_schema.columns where column_name like '%field%'
Yes you can:
select o.type, o.name from sys.columns c
join sys.objects o on c.object_id = o.object_id
where c.name = #col_to_find
Or you can install the free Red Gate Search add-in.

Easy way to find out how many rows in total are stored within SQL Server Database?

I'm looking for easy way to count all rows within one SQL Server 2005/2008 database (skipping the system tables of course)? I know i could use
SELECT COUNT (COLUMN) FROM TABLE
and do it for each table and then add it up but would prefer some automated way?
Is there one?
SELECT SUM(row_count)
FROM sys.dm_db_partition_stats
WHERE index_id IN (0,1)
AND OBJECTPROPERTY([object_id], 'IsMsShipped') = 0;
This will be accurate except for, potentially, any rows that are being added or removed within a transaction at the time you run the query. And it won't have the expense of hitting individual tables.
But as I mentioned in another comment, I'm not sure how this helps you determine "how much data" your database holds. How many rows, sure, but if I have 10 glasses, each half full of water, and you have 5 glasses, each completely full, which of us has more water?
This was my answer to a similar question today:
SQL Server 2005 or later gives quite a useful report showing table sizes - including row counts etc. It's in Standard Reports - and it is Disc Usage by Table.
Programmatically, there's a nice solution at: http://www.sqlservercentral.com/articles/T-SQL/67624/
Try:
SELECT
[TableName] = so.name,
[RowCount] = MAX(si.rows)
FROM
sysobjects AS so,
sysindexes AS si
WHERE
so.xtype = 'U'
AND
si.id = OBJECT_ID(so.name)
GROUP BY
so.name
ORDER BY
2 DESC
This is the indexed rows. This is probably only an approximation, as databases change a lot and some stuff might not be indexed, but this will be fast.
EDIT: Note that so.xtype is user types, making the assumption you do not want the system stuff and only "real" data stuff.
EDIT2: no flames note: probably a bad idea to query on the sysobjects table :).
EDIT3: to specifically address requirement, and no associative joins :)
SELECT sum(mycount) from
(SELECT
MAX(si.rows) AS mycount
FROM
sysobjects AS so
join sysindexes AS si on si.id = OBJECT_ID(so.name)
WHERE
so.xtype = 'U'
GROUP BY
so.name
) as mylist
We know that sp_spaceused, when passed a table name, will return a row count, so we can examine what it does - it queries sys.dm_db_partition_stats - and copy it to get this:
SELECT
SUM(ddps.row_count) TotalRows
FROM
sys.indexes i
INNER JOIN sys.objects o ON i.OBJECT_ID = o.OBJECT_ID
INNER JOIN sys.dm_db_partition_stats ddps ON
o.OBJECT_ID = ddps.OBJECT_ID
AND i.index_id = ddps.index_id
WHERE
i.index_id < 2
AND o.is_ms_shipped = 0 -- to exclude system tables
Curious requirement though, I have to say...
You could query sysindexes, look at the rowcnt value for the clustered index on each table. But I'm not sure exactly how up to date that is.
Alternatively, something like this (briefly tested on a small test db):
CREATE TABLE #TableRowCount (TableName NVARCHAR(128), RowCnt BIGINT)
INSERT #TableRowCount (TableName, RowCnt)
EXECUTE sp_msforeachtable 'SELECT "?", COUNT(*) FROM ?'
SELECT SUM(RowCnt) AS TotalRowCount FROM #TableRowCount
DROP TABLE #TableRowCount
Check out the undocumented stored procedure sp_MSForEachTable. Using it you can run a Count(*) on every table in the database. For your specific issue:
EXEC sp_MSforeachtable 'SELECT ''?'', Count(*) as NumberOfRows FROM ?'
I'm not sure if older version of MS SQL has the information_shema SQL standard for data dictionary.
You can do something like:
SELECT SUM(table_rows)
FROM information_schema.tables
WHERE table_schema = 'DATABASENAME'