I have 6 variables that is: #SourceDatabase, #SourceSchema, #SourceTable, #TargetDatabase, #TargetSchema, #TargetTable
Im writing a query that should join values from INFORMATION_SCHEMA.COLUMNS.
Like this:
SELECT a.COLUMN_NAME, b.COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS a
LEFT OUTER JOIN INFORMATION_SCHEMA b
ON b.TABLE_SCHEMA = #SourceSchema
AND b.TABLE_NAME = #SourceTable
AND b.COLUMN_NAME = a.COLUMN_NAME
WHERE a.TABLE_SCHEMA = #TargetSchema
AND a.TABLE_NAME = #TargetTable
However, after I introduced the database-attributes, to do comparison cross databases, i just noticed that i dont think i can use the same query without making it dynamic as a String and putting databasename in front of INFORMATION_SCHEMA. Like DECLARE #SQL nvarchar(254) = 'SELECT * FROM ' + #SourceDatabase + '.INFORMATION_SCHEMA ...'. etc etc
Since im not really a fan of doing dynamic sql, im wondering if you guys have any clever solutions to do what im trying to do without going dynamic?
Dynamic SQL is certainly the easiest way to handle this kind of thing, but you are certain this is not an option?
The only other alternative I can think of is to UNION ALL on all of your databases, with an additional db name column:
SELECT 'db1' AS dbName, *
FROM db1.sys.columns
UNION ALL
SELECT 'db2' AS dbName, *
FROM db2.sys.columns
The collation needs to be the same in both databases. But Dynamic SQL would be easier, and could be made to work for any database, rather than just those in your union list.
Related
I have 4 columns that are repeated in all the tables in the database and I have to delete them
How can I do this deletion without having to enter table by table?
This code will output the necessary SQL to make the changes.
STRING_AGG is used twice to group up the columns and tables. QUOTENAME is used to place brackets around names correctly.
SELECT STRING_AGG(
N'ALTER TABLE ' + QUOTENAME(SCHEMA_NAME(t.schema_id)) + N'.' + QUOTENAME(t.object_id) + N'
' + c.ColumnSql, N'
')
FROM sys.tables t
CROSS APPLY (
SELECT ColumnSql = STRING_AGG(CAST(N'DROP COLUMN ' + QUOTENAME(c.name) AS nvarchar(max), N'
')
FROM sys.columns c
WHERE c.object_id = t.object_id
AND c.name IN (
'ID_Integracion_CodBodega',
'ID_Integracion_FechaUltRep',
'ID_Integracion_ControlTrigger',
'ID_Integracion_CodBodega_Origen'
)
) c
You can execute it all together by using
DECLARE #sql nvarchar(max) = (
SELECT STRING_AGG.....
);
EXEC(#sql);
I caution you against using INFORMATION_SCHEMA because it is only there for compatibility.
SQL Server provides system information schema views that can be queried to retrieve information about the database.
In your case, the COLUMNS view can be used to fetch the names of all tables containing a specific column name.
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN (
'ID_Integracion_CodBodega',
'ID_Integracion_FechaUltRep',
'ID_Integracion_ControlTrigger',
'ID_Integracion_CodBodega_Origen'
);
From there, you can use the normal process to delete a column from an existing table.
ALTER TABLE [table_name] DROP COLUMN [column_name];
You should be very careful with this approach. It is easy to drop a column you didn't mean to.
Be aware of any constraints/dependencies in your database schema that you might be affecting with this action.
Are there constraints on your tables that will be affected by the removal of these columns? (Especially ON DELETE CASCADE constraints that may impact other tables).
Are there views/stored procedures/triggers that depend on these columns?
Do you have queries/dynamic SQL that will be impacted by the removal of these columns?
I have 2 tables corporate and corporate_copy. Initially they were same in structure but people started added new columns into corporate and forgot do do so for corporate_copy.
Somewhere in the application there is less used functionality that copies data from corporate to corporate_copy and that kept failing without anyone noticing. Now I have to add 28 columns (ofcourse with same type and length and constraints etc....).
I know it can be done in one ALTER TABLE statement but I still feel it is lengthy task.
Do we have any luxury that will make copy table same as main table by keeping data and adding default values in newly added columns?
I am asking much but is there anything like that?
--Generate a dynamic query which contain all the missing column list and Execute it
--for eg I tried Something
BEGIN TRAN
DECLARE #SqlSelect NVARCHAR(MAX),#ColumnDeclaration VARCHAR(2000)
SELECT DISTINCT ' '+COLUMN_NAME+' '+ DATA_TYPE +' '+ISNULL(CONVERT(NVARCHAR(10), CHARACTER_MAXIMUM_LENGTH ),'')+' 'Missing_Column INTO #T FROM INFORMATION_SCHEMA.COLUMNS a
WHERE a.column_name not in (SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS b
WHERE b.table_name in ('Corporate_Copy'))
and a.table_name in ('Corporate')
SELECT #ColumnDeclaration=STUFF((
SELECT ', ' + Missing_Column
FROM #T
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(max)'), 1, 1, '')
SET #SqlSelect=' ALTER TABLE Corporate_Copy Add'+ #ColumnDeclaration + ');'
PRINT #SqlSelect
ROLLBACK TRAN
You could use schema compare, found in SQL Server data tools (free) to generate a change script automatically.
But if this is just a copy, you could just run this:
DROP TABLE Corporate_Copy;
SELECT *
INTO Corporate_Copy
FROM Corporate;
It's not clear whether you really need to preserve the data in the copy. If so, it's not really a copy is it?
From SQL-Server 2015, you can use the following query to extract all different columns between 2 tables:
select distinct a.* from INFORMATION_SCHEMA.COLUMNS a
where a.column_name not in (select column_name from INFORMATION_SCHEMA.COLUMNS b
where b.table_name in ('tbl_A'))
and a.table_name in ('tbl_B')
order by a.column_name
The output gives you enough information to create a simple script to add the columns which are missing:
For exmaple:
Alter table tbl_A ADD res.Column_Name res.Data_Type ....
generate CREATE script in SSMS (right-click on table, then "script table as...")
Delete all things that already exists. Usually they are in the begining and it's a simple
change CREATE to ALTER ... ADD
That should be possible using SELECT INTO, for example the following SQL statement creates a backup copy of corporate:
SELECT * INTO corporate_copy
FROM corporate ;
I want to run a SELECT statement on only some specific databases. The list of databases is returned by this query:
DECLARE #OneWeekAgo DATETIME
SELECT #OneWeekAgo = DATEADD(week,-1,GETDATE())
select distinct DB_NAME(database_id) DatabaseName
into #temp
from sys.dm_db_index_usage_stats
where DB_NAME(database_id) like 'TTT[_][a-z]%'
and DB_NAME(database_id) not like '%test%'
and last_user_update > #OneWeekAgo
Now on all of these databases returned, I want to run a simple query:
SELECT *
FROM TTT_Clients
WHERE country like 'SWEDEN'
How do I do that? I get errors in the "IN (SELECT DISTINCT...)" line using something like this:
exec sp_msforeachdb ' use [?] IF ''?'' in (select distinct DB_NAME(database_id) DatabaseName
from sys.dm_db_index_usage_stats
where DB_NAME(database_id) like ''TTT[_][a-z]%''
and DB_NAME(database_id) not like ''%test%'')
BEGIN
SELECT * FROM TTT_Clients WHERE country like ''SWEDEN''
END
You didn't specify the error, and I don't know this for sure, but I'm guessing that sys.dm_db_index_usage_stats returns the same information regardless of database you are using (server wide view).
I think you want something like this...
exec sp_msforeachdb ' use [?];
IF ('[?]' NOT LIKE ''%test%'' AND EXISTS(SELECT * FROM sys.tables WHERE name LIKE ''TTT[_][a-z]%''))
BEGIN
SELECT * FROM TTT_Clients WHERE country like ''SWEDEN''
END
'
Re-using your filters, I don't know if they are correct or not. Basically we are checking if the table in question exists in the database. Since you are only selecting from TTT_Clients I would suggest just filtering WHERE name = ''TTT_Clients'' rather than that regex that just matches it.
I am working on application which can deal with multiple database servers like "MySQL" and "MS SQL Server".
I want to get tables' names of a particular database using a general query which should suitable for all database types. I have tried following:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='BASE TABLE'
But it is giving table names of all databases of a particular server but I want to get tables names of selected database only. How can I restrict this query to get tables of a particular database?
Probably due to the way different sql dbms deal with schemas.
Try the following
For SQL Server:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG='dbName'
For MySQL:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA='dbName'
For Oracle I think the equivalent would be to use DBA_TABLES.
Stolen from here:
USE YOURDBNAME
GO
SELECT *
FROM sys.Tables
GO
The following query will select all of the Tables in the database named DBName:
USE DBName
GO
SELECT *
FROM sys.Tables
GO
Just put the DATABASE NAME in front of INFORMATION_SCHEMA.TABLES:
select table_name from YOUR_DATABASE.INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'
USE DBName;
SELECT * FROM sys.Tables;
We can deal without GO in-place of you can use semicolon ;.
In mysql, use:
SHOW TABLES;
After selecting the DB with:
USE db_name
In order if someone would like to list all tables within specific database without using the "use" keyword:
SELECT TABLE_NAME FROM databasename.INFORMATION_SCHEMA.TABLES
This works Fine
SELECT
*
FROM
information_schema.tables;
I did not see this answer but hey this is what I do :
SELECT name FROM databaseName.sys.Tables;
To select the database query below :
use DatabaseName
Now
SELECT * FROM INFORMATION_SCHEMA.TABLES
Now you can see the created tables below in console .
PFA.
For Mysql you can do simple. SHOW TABLES;
select * from sys.tables
order by schema_id --comments: order by 'schema_id' to get the 'tables' in 'object explorer order'
go
In our Oracle DB (PL/SQL) below code working to get the list of all exists tables in our DB.
select * from tab;
and
select table_name from tabs;
both are working. let's try and find yours.
SELECT TABLE_NAME
FROM your_database_name.INFORMATION_SCHEMA.TABLES
ORDER BY TABLE_NAME;
Exec sp_MSforeachtable 'Select ''?'''
USE dbName;
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE (TABLE_SCHEMA = 'dbName' OR TABLE_SCHEMA = 'schemaName')
ORDER BY TABLE_NAME
If you are working with multiple schemata on an MS SQL server, then SELECT-ing TABLE_NAME without also simultaneously selecting TABLE_SCHEMA might be of limited benefit, so I have assumed we are interested in the tables belonging to a known schema when using MS SQL Server.
I have tested the query above with SQL Server Management Studio using an SQL Server database of mine and with MySQL Workbench using a MySQL database, and in both cases it gives the table names.
The query bodges Michael Baylon's two different queries into one that can then run on either database type. The first part of the WHERE clause works on MySQL databases and the second part (after the OR) works on MS SQL Server databases. It is ugly and logically a little incorrect as it supposes that there is no undesired schema with the same name as the database. This might help someone who is looking for one single query that can run on either database server.
UPDATE FOR THE LATEST VERSION OF MSSQL SERVER (17.7)
SELECT name FROM sys.Tables WHERE type_desc = 'USER_TABLE'
Or SELECT * for get all columns.
Yes oracle is :
select * from user_tables
That is if you only want objects owned by the logged in user/schema otherwise you can use all_tables or dba_tables which includes system tables.
Building from Michael Baylon's answer, I needed a list which also included schema information and this is how I modified his query.
SELECT TABLE_SCHEMA + '.' + TABLE_NAME as 'Schema.Table'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG = 'dbName'
ORDER BY TABLE_SCHEMA, TABLE_NAME
Simply get all improtanat information with this below SQL in Mysql
SELECT t.TABLE_NAME , t.ENGINE , t.TABLE_ROWS ,t.AVG_ROW_LENGTH,
t.INDEX_LENGTH FROM
INFORMATION_SCHEMA.TABLES as t where t.TABLE_SCHEMA = 'YOURTABLENAMEHERE'
order by t.TABLE_NAME ASC limit 10000;
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_NAME
for postgres it will be:
SELECT table_name
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema = 'your_schema' -- probably public
How can I Select all columns from all tables from the DB, like:
Select * From *
in SQL Server 2008???
The table list it´s very very big, and have so many columns, is it possible to do it without writing the column names?
Or maybe make a select that returns the name of the tables.
This SQL will do this...
DECLARE #SQL AS VarChar(MAX)
SET #SQL = ''
SELECT #SQL = #SQL + 'SELECT * FROM ' + TABLE_SCHEMA + '.[' + TABLE_NAME + ']' + CHAR(13)
FROM INFORMATION_SCHEMA.TABLES
EXEC (#SQL)
Try this, works fine
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
then you could add
WHERE TABLE_NAME LIKE '' AND COLUMN_NAME LIKE ''
SELECT t.name AS table_name,
SCHEMA_NAME(schema_id) AS schema_name,
c.name AS column_name
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID where t.name = 'ProductItem' AND C.name like '%retail%'
ORDER BY schema_name, table_name
It is possible to retrieve the name of all columns from sys.columns
It is possible to retrieve the name of all table from sys.tables
But is impossible to retrieve all the data from all the tables. As soon as more than one table is involved in a query, a JOIN is necessary. Unless join conditions are provided, tables are joined as full Cartesian product, meaning each row from each table is matched with each row from ll other tables. Such a query as you request would produce for 10 tables with 10 records each no less than 10e10 records, ie. 100 billion records. I'm sure you don't want this.
Perhaps if you explain what you what to achieve, not how, we can help better.
To select * from each table, one after another, you can use the undocumented but well known sp_msforeachtable:
sp_msforeachtable 'select * from ?'
If you are going to send to Excel, I would suggest you use the export wizard and simply select all the tables there. In the object browser, put your cursor on the database name and right click. Chose Tasks - Export Data and follow the wizard. WHy anyone would want an entire database in Excel is beyond me, but that's the best way. If you need to do it more than once you can save the export in an SSIS package.
In SQL Server 2016 Management Studio ( Version: 13.0.15900.1), to get all column names in a specified table, below is the syntax:
**Select name from [YourDatabaseName].[sys].[all_columns]
where object_id=(Select object_id from [YourDatabaseName].[sys].[tables]
where name='YourTableName')**