SQL Server stored procedure error handling with if exists - sql-server

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

Related

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

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

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

Executing dynamic SQL with return value as a column value for each rows

I have a rather simple query that I started to modify in order to remove temp table as we have concurrency issues over many different systems and clients.
Right now the simple solution was to break up the query in multiple separate queries to replicate what SQL was doing before.
I am trying to figure out a way to return the result of a dynamic SQL query as a column value. The new query is quite simple, it look in the system objects for all table with specific format and output. What i am missing is that for each record i need to output the result of a dynamic query on each of those table.
The query :
SELECT [name] as 'TableName'
FROM SYSOBJECTS WHERE xtype = 'U'
AND (CHARINDEX('_PCT', [name]) <> 0
OR CHARINDEX('_WHT', [name]) <> 0)
All these table have a common column called Result which is a float. What i am trying to do is return the count of this column under some WHERE clause that is generic and will work will all tables as well.
A desired query (i know it's not valid) would be :
SELECT [name] as 'TableName',
sp_executesql 'SELECT COUNT(*) FROM ' + [name] + ' WHERE Result > 0 OR (Result < 139 AND CurrentIndex < 15)' as 'ResultValue'
FROM SYSOBJECTS WHERE xtype = 'U'
AND (CHARINDEX('_PCT', [name]) <> 0
OR CHARINDEX('_WHT', [name]) <> 0)
Before it used to be easy. We had a temp table with 2 columns and were filling the table name first. Then we iterate on the temp table and execute the dynamic sql and return the value in an OUTPUT variable and simply update the record of the temp table and finally return the table.
I have tried a scalar function but it doesn't support dynamic SQL so it doesn't work. I would rather not create the 13,000~ different queries for the 13,000~ tables.
I have tried using a reference table and use trigger to update the status but it slow the system way to much. The average tables insert and delete 28 millions records. The original temp table query only took 5-6 minutes to execute due to very good indexing and now we are reaching 25-30 minutes.
Is there any other solution available than Querying the table list then the Client query each table one by one to know it status ?
We are using SQL Server 2017 if some new features are available now
You can use this script for your purpose (tested in SQL Server 2016).
Updated: It should work now as the results are a single set now.
EXEC sp_msforeachtable
#precommand = 'CREATE TABLE ##Statistics
(TableName varchar(128) NOT NULL,
NumOfRows int)',
#command1 ='INSERT INTO ##Statistics (TableName, NumOfRows)
SELECT ''?'' Table_Name, COUNT(*) Row_Count FROM ? WHERE Result > 0 OR (Result < 139 AND CurrentIndex < 15)',
#postcommand = 'SELECT TableName, NumOfRows FROM ##Statistics;
DROP TABLE ##Statistics'
,#whereand = ' And Object_id In (Select Object_id From sys.objects
Where name like ''%_PCT%'' OR name like ''%_WHT%'')'
For more details on sp_msforeachtable Please visit this link

Retrieve column name through db link in Oracle 11g

I want to retrieve column names from a table through a db link but I'm not able to do it...
Although this query is working
SELECT *
FROM myTableName#myDbLink;
the following one is not:
SELECT column_name
FROM all_tab_columns#myDbLink
WHERE table_name = 'myTableName'
What's the correct way of retrieving the column names?
CaSE mATterS.
In Oracle, table names are - by default - in UPPERCASE, so - try with
SELECT column_name
FROM all_tab_columns#myDbLink
WHERE table_name = 'MYTABLENAME'

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.

Resources