doing select from stored procedure such as : select * from sp_tables - sql-server

is there a way to simply select the result returned from sp_tables?

No there isn't.
But you could try to replace sp_tables by querying the information_schema.
For example:
sp_tables 'T_Raum'
You can substitute with this:
SELECT
TABLE_CATALOG AS TABLE_QUALIFIER,
TABLE_SCHEMA AS TABLE_OWNER,
TABLE_NAME,
CASE TABLE_TYPE
WHEN 'BASE TABLE' THEN 'TABLE'
ELSE TABLE_TYPE
END AS TABLE_TYPE,
NULL AS REMARKS
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE != 'VIEW'
AND TABLE_NAME = 'T_Raum'
I don't know what exactly sp_tables does, or what you need it for, but at least in this case, it seems to do the above schema query.

If you call sp_tables, the result you get is the result of a SELECT statement.
In that respect, it is no different than any store procedure that returns a result set.

If you mean you want to filter the resultset returned by that sproc then depending on what you want to filter on, you can pass in params to that sproc (e.g. #table_name parameter, which supports wildcards). Check out the BOL ref on sp_tables
Alternatively, you will need to insert the results into a temp table and select from that.
Or finally, depending on what you want, you could query the sys tables directly. If only interested in tables:
SELECT *
FROM sys.tables
WHERE...

If you want to select from each table, you can use the undocumented sp_msforeachtable command:
sp_msforeachtable 'SELECT * FROM ?'
The ? is a wildcard that indicates the current table name, and the command needs to be a string enclosed in single quotes just like in other Dynamic SQL.

Related

How to get definition of all the VIEWS in a Snowflake database?

The ask is to get the definition of all the views from Production environment and refresh the lower environment. I assume, GET_DDL in a loop will suffice the need but not sure how to implement it. Please advise.
Assuming that VIEW_DEFITION is not enough:
SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, VIEW_DEFINITION
FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_SCHEMA != 'INFORMATION_SCHEMA';
and GET_DDL is required:
DECLARE
CUR CURSOR FOR SELECT CONCAT_WS('.',TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME) AS name
FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_SCHEMA NOT IN ('INFORMATION_SCHEMA');
BEGIN
CREATE OR REPLACE TEMPORARY TABLE temp_view_defs(view_name TEXT, definition TEXT);
FOR rec IN CUR DO
EXECUTE IMMEDIATE REPLACE('INSERT INTO temp_view_defs(view_name, definition)
SELECT ''<view_name>'', GET_DDL(''TABLE'', ''<view_name>'')'
,'<view_name>'
,rec.name);
END FOR;
LET rs RESULTSET := (SELECT * FROM temp_view_defs);
RETURN TABLE(rs);
END;
Sample output:
Check this. You can download the results and use it to get the DDL of all views, at once.
SELECT 'SELECT GET_DDL(''VIEW'',''' || table_name || ''');' AS stmt
FROM INFORMATION_SCHEMA.views
WHERE table_name NOT IN('TABLES','COLUMNS','SCHEMATA','SEQUENCES','VIEWS','TABLE_PRIVILEGES','USAGE_PRIVILEGES','DATABASES','REPLICATION_DATABASES','REPLICATION_GROUPS','FUNCTIONS','PROCEDURES','OBJECT_PRIVILEGES','OBJECT_PRIVILEGES','FILE_FORMATS','APPLICABLE_ROLES','ENABLED_ROLES','STAGES','REFERENTIAL_CONSTRAINTS','TABLE_CONSTRAINTS','INFORMATION_SCHEMA_CATALOG_NAME','LOAD_HISTORY','TABLE_STORAGE_METRICS','PIPES','EXTERNAL_TABLES','LOGGERS','EVENT_TABLES','PACKAGES');
Thanks all for suggesting your solutions. I found below code is much more close to my requirement; copy entire VIEWS in one go:
select view_definition from information_schema.views
where table_schema = 'XYZ'
Copy the the view_definition > Execute it.

Invalid column name 'TABLETYPE' in INFORMATION_SCHEMA.TABLES

The following statement:
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLETYPE = 'VIEW';
Throws 'Invalid column name 'TABLENAME'. But the column is shown in query.
I tried to replace 'TABLENAME' for 'tablename' and nothing worked.
I read that this could be a InteliSense cache problem, that is needs to be refreshed. But I execute statements like this in my application, so unless I can be able to do it via sql, that is not really an option for me.
Correct me if I am wrong :)
The 'Table Type' column has an underscore in it, so you'll want to use:
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'VIEW';

Database issue for everyone (QUERY)

I want to create a query that generates the table name.
I tried something like this :
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='mytableName'
but it return an empty query. So , any ideas ? Thx
Why WHERE AND TABLE_SCHEMA='mytableName'
The AND is invalid at this point.
Besides the Tablename is in the column TABLE_NAME not TABLE_SCHEMA, maby you should try to filter using the schema name instead of the table name like:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='YOUR_SCHEMA_NAME'
Or if you need information regarding a specific table:
SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='YOUR_TABLE_NAME'
To start with: that query is invalid (remove the AND).
2nd it's empty because there are no tables within the schema (also called database) named mytableName.
Also take a look at SHOW TABLES (documentation) and SHOW DATABASES (documentation)
There is incorrect syntax at "WHERE AND".
You should execute:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='mytableName'
You should try TABLE_SCHEMA='dbo', it looks like your schema 'mytableName' is really empty.

Query on multiple databases (SQL server)

I have multi databases with same structure its name like that "Client1234" the different in numbers beside "client" i have table called "Transactions" inside each database and i want to run query to get count all raws in "transactions" table in all databases.
also when i select database i need to check it has the client word and it has numbers beside the word.
Try to use sp_msforeachdb stored procedure like so:
create table #temp ([rows] int, [client] varchar(100))
exec sp_msforeachdb '
if ''?'' like ''Client%'' and exists(select * from ?.sys.tables t where t.name = ''Transactions'')
begin
insert into #temp select count(*), ''?'' from ?..Transactions
end
'
select * from #temp
drop table #temp
You can use dynamic SQL to create these queries:
select 'select count(*) from ' + name + '.dbo.transactions'
from master..sysdatabases
where name like 'Client%'
and isnumeric(substring(name,6,1))
This would return a result set with each row being a SQL query to count a specific database. It could be consumed by a programming language, used as a cursor, etc.. If you provide more detail I may be able to provide a better example.
When using Fosco's method, it is a good idea to put in brackets [] around the database name:
SELECT 'SELECT count(*) FROM ' + '[' + name + ']' + '.dbo.transactions'
FROM master..sysdatabases
WHERE name like 'Client%' and isnumeric(substring(name,6,1))
If the name and number of the databases you wish to query is not known beforehand then you can only do this by using a dynamic query. You'll need to generate a script like
SELECT COUNT(*) FROM Client1.dbo.Transactions
SELECT COUNT(*) FROM Client2.dbo.Transactions
...
Of course you need to have your appropriate permissions in place for each database.

How to tell the data types after executing a stored procedure?

Is there a way when executing a stored procedure in Management Studio to get the data types of the result sets coming back? I'm looking for something like functionality of when you pass a table name to sp_help
You do get to look at the types though, if you call the stored procedure via ADO, ADO.NET, ODBC or the likes: The resulting recordsets have the type information you are looking for. Are you really restricted to Management Studio?
Your best bet would be to change the stored procedure to a function. But that only works if your environment allows it.
No easy way comes to mind without parsing syscomments to see what it's querying from where. If you can edit the SP to select XML, you can append XML_INFO to the query to get the schema back.
Actually, you can do it from within an SP:
EXEC ('if exists (select * from sys.tables where name = ''tmp_TableName'') drop table tmp_TableName')
EXEC ('select * into tmp_TableName from MyTable')
-- Grab the column types from INFORMATION_SCHEMA here
EXEC ('if exists (select * from sys.tables where name = ''tmp_TableName'') drop table tmp_TableName')
Although, I think there must be a better way.
It's not the most elegant solution, but you could use OPENROWSET to put the stored proc results into a table, then use sp_help to get a description of it.
eg
select * into tmp_Results
from openrowset( 'SQLOLEDB.1'
, 'Server=your_server_name;Trusted_Connection=yes;'
, 'exec your_stored_proc')
exec sp_help 'tmp_Results'
drop table tmp_Results
You could always use an actual table that is garrenteed to be unique. It's a kludge, but it's an option. This will not work inside a stored proc though.
if exists (select * from sys.tables where name = 'tmp_TableName')
drop table tmp_TableName
go
select * into tmp_TableName from MyTable
--do some stuff
go
if exists (select * from sys.tables where name = 'tmp_TableName')
drop table tmp_TableName
go

Resources