T-SQL Check if the database contains certain tables and columns MSSQL - sql-server

My goal is to continue in the procedure only with the database selected if it contains a specific table and a specific column.
So that I don't get an error message later when selecting that this column doesn't exist.
Background:
It is the case that database A table A has a more current status than database B with table A. In database B of table A a column is missing, which is the reason for the error that this column does not exist. Which I also do not want to add.
This is my attempt so far:
exec sp_MSforeachdb
'
use [?]
IF (''?'' NOT LIKE ''%example%'' AND ''?'' NOT LIKE ''%example_two%''
AND EXISTS(Select 1 from sys.tables where name = ''Table1'')
AND EXISTS(Select 1 from sys.tables where name = ''Table2'')
AND ''?'' NOT IN (SELECT * FROM Database.dbo.Blacklist)
)
BEGIN
IF(EXISTS(SELECT myColumn FROM Table1 Where ID = 5 AND XYZ = 3)) BEGIN.....'
Even when i switch instead of
..
AND EXISTS(Select 1 from sys.tables where name = ''Table1'')
AND EXISTS(Select 1 from sys.tables where name = ''Table2'')
..
To:
SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = ''Table1''
AND COLUMN_NAME = ''MyExample''
it will not work the error log outputs: Incorrect syntax near 'TableXX'.
The error log gives me all databases that are practically checked, system databases as well.
Alternative it would also be helpful if someone knows how to use a case when in the select by trying to store an alternative value once the column does not exist e.g. like this:
'SELECT...
CASE WHEN exists(
SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_NAME =''TableX'' AND COLUMN_NAME = ''ColumnX'')
THEN ''ST.ColumnX''
ELSE ''0 AS ColumnX''
END
FROM ...'
I just want to select databases that have the valid table and column, whenever I don't exist I take another table, this works until I find a table where a column doesn't exist, the column is however my select statement therefore I get an error, I want to focus on the alternative question, is there a way to check if the column exists in the current table? before assigning a value?
Case WHEN ColumnX exists THEN (ValueOfColumnX) ELSE 0 END AS Column.
Thank you in advance for any help

Use one single quotes when you are specifying the names of your tables and columns
SELECT 1 FROM your_databasename.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Table1'
AND COLUMN_NAME = 'MyExample'
If you want to check if a column exists in a table try looking into this thread

Related

SQL checks Column names first instead of condition and gives me an Error Invalid column name. How to fix this?

I am trying to test a column in a source table to check if it has any duplicate values. But here the situation is, the source table does not contain that column always. I have a code where it runs fine if the Column exists but gives me an Invalid column name error if the column doesn't exist.
I tried many codes where I check for the table name and the column name before executing the code. None of them worked. Below is such example:
IF EXISTS(
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = 'SourceData'
AND COLUMN_NAME = 'dataid')
Begin
select'SourceData' as TableName, a.dataid, b.dupcount from SourceData a inner join (select dataid, count(*) as dupcount from SourceData group by dataid having count(*) > 1) b on a.dataid = b.dataid
End
I want a code where it should run even if the column doesn't exist where it should give me No Output or NULL Output. If that column exists then it should check for the duplicate values in that column.
The problem is that the statements are all checked at compile time already and when the objects don't exist that fails.
You can resolve this by using EXECUTE to execute your query. Though it would still fail if the objects aren't there, you can now first check for their existence and skip the EXECUTE if they aren't there. That way the compiler never "sees" the query and can never nag about the objects' non-existence.
IF EXISTS (...)
BEGIN
EXECUTE ('SELECT ...'); -- your query goes in there as a string constant
END
ELSE
BEGIN
-- do something else
END;
You can use either dynamic SQL or better is to use stored procedures for that. This is an example:
CREATE TABLE testMissingColumn
(
a int
)
GO
ALTER TABLE testMissingColumn ADD b INT;
-- this will fail as even if it exists already, at runtime it wasn't there
IF EXISTS ( SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'testMissingColumn'
AND COLUMN_NAME = 'b' )
SELECT b FROM testMissingColumn;
-- will not fail as query is unknown at runtime
IF EXISTS ( SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'testMissingColumn'
AND COLUMN_NAME = 'b' )
EXEC('SELECT b FROM testMissingColumn; ');
GO
-- stored procedures doesn't care about missing objects :)
CREATE PROCEDURE sfFestMissingColumn
AS
SELECT b FROM testMissingColumn;
GO
EXEC sfFestMissingColumn

SQL Server stored procedure error handling with if exists

I have five databases, In that three databases having column Countries and two databases having column Countryrelease..
I am using a cursor, so if I use exists that particular column is throwing an error that column not exists how to handle this one.
Syntax
if exists(select 1 from table where column name='Countries')
select do some operation
else
select do some operation
You want to make use of the meta data within the SQL instance.
This will work for you ...
if (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'YourTableName' AND COLUMN_NAME = 'Countries') = 1
-- The "Countries" column exists
select do some operation
else
select do some operation

Deleting specific rows from all tables

I have a database with a lot of tables.
In each table there is a column named "LicenseID" (bigint). How can I delete all rows, from all tables, that contain the value "2" in the column "LicenseID" ?
Best regards!
You didn't mentioned which database are you working with.
I assume it is SQL Server
First check your result with following query
SELECT * FROM table WHERE LicenseID LIKE '%2%'
or
SELECT * FROM table WHERE Contains(LicenseID, 2) > 0
Then Delete all those rows with above condition.
DELETE FROM table WHERE LicenseID LIKE '%2%'
or
DELETE FROM table WHERE Contains(LicenseID, 2) > 0
I have not tested it and don't know what type of database are you using. Answer can be little different in different databases.
You can use INFORMATION_SCHEMA.COLUMNS to generate the delete statements dynamically.
Something like this should do the trick:
DECLARE #Sql varchar(max) = ''
SELECT #Sql = #Sql + 'DELETE FROM '+ TABLE_NAME +' WHERE LicenseID = 2; '
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = 'LicenseID'
EXEC(#Sql)
The reason I've used INFORMATION_SCHEMA.COLUMNS and not INFORMATION_SCHEMA.TABLES is to prevent an error in case there is a table that doesn't contain the LicenseID column.

SQL Server ambiguous query validation

I have just come across a curious SQL Server behaviour.
In my scenario I have a sort of dynamic database, so I need to check the existence of tables and columns before run queries involving them.
I can't explain why the query
IF 0 = 1 -- Check if NotExistingTable exists in my database
BEGIN
SELECT NotExistingColumn FROM NotExistingTable
END
GO
executes correctly, but the query
IF 0 = 1 -- Check if NotExistingColumn exists in my ExistingTable
BEGIN
SELECT NotExistingColumn FROM ExistingTable
END
GO
returns Invalid column name 'NotExistingColumn'.
In both cases the IF block is not executed and contains an invalid query (the first misses a table, the second a column).
Is there any reason why SQL engine checks for syntax erorrs just in one case?
Thanks in advance
Deffered name resolution:
Deferred name resolution can only be used when you reference nonexistent table objects. All other objects must exist at the time the stored procedure is created. For example, when you reference an existing table in a stored procedure you cannot list nonexistent columns for that table.
You can look through the system tables for the existence of a specific table / column name
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 c.name LIKE '%colname%'
AND t.name LIKE '%tablename%'
ORDER BY schema_name, table_name;
The query above will pull back all tables / columns with partial match of a columnname and tablename, just change the like % for exact match.

SQL View Columns

This is probably a strange question... Hopefully, someone enjoys the more esoteric portion of SQL. :)
I have some views with many columns. The column widths are obstructive to reviewing the data. Once a column width is manually adjust and the view is saved, the column is perpetually saved at that width unless manually changed and again saved.
This makes me wonder how SQL saves column widths. Is there a table containing that data? If so, could an updated query revise all the columns for a given table to a defined width? If so, how?
Just FYI, my DBA and I spent a good while trying to figure this out. I am not asking without first endeavoring to solve it myself. I am a novice with SQL and hope for more experienced guidance.
They are stored in the extended properties. You can review them either in the properties window for the view in question or by scripting them out. If scripting out you need to ensure that you have selected the option to script extended properties hidden behind the advanced button. You can also set the default options in the options of SSMS.
Note that if you have not used the view designer there will be no extended properties.
Solution: use sp_refreshview (this demo shows that SQL Server doesn't automatically update metadata information for dbo.MyView after I change the maximum length for dbo.MyTable.Col2 and we have to use sp_refreshview [or ALTER VIEW, DROP & CREATE] to update metadata for the view):
IF EXISTS(SELECT * FROM sys.views t WHERE t.object_id = OBJECT_ID(N'dbo.MyView'))
BEGIN
DROP VIEW dbo.MyView;
END
IF EXISTS(SELECT * FROM sys.tables t WHERE t.object_id = OBJECT_ID(N'dbo.MyTable'))
BEGIN
DROP TABLE dbo.MyTable;
END
CREATE TABLE dbo.MyTable
(
Col1 INT IDENTITY(1,1) PRIMARY KEY,
Col2 VARCHAR(3) NULL
);
GO
CREATE VIEW dbo.MyView
AS
SELECT * FROM dbo.MyTable;
GO
SELECT cols.COLUMN_NAME, cols.DATA_TYPE, cols.CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_SCHEMA = 'dbo'
AND cols.TABLE_NAME = 'MyView'
AND cols.COLUMN_NAME = 'Col2'
GO
/*
COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH
----------- --------- ------------------------
Col2 varchar 3
*/
ALTER TABLE dbo.MyTable
ALTER COLUMN Col2 VARCHAR(10);
GO
SELECT cols.COLUMN_NAME, cols.DATA_TYPE, cols.CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_SCHEMA = 'dbo'
AND cols.TABLE_NAME = 'MyView'
AND cols.COLUMN_NAME = 'Col2'
GO
/*
COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH
----------- --------- ------------------------
Col2 varchar 3
*/
EXEC sp_refreshview 'dbo.MyView';
GO
SELECT cols.COLUMN_NAME, cols.DATA_TYPE, cols.CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_SCHEMA = 'dbo'
AND cols.TABLE_NAME = 'MyView'
AND cols.COLUMN_NAME = 'Col2'
GO
/*
COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH
----------- --------- ------------------------
Col2 varchar 10
*/

Resources