How to do an IF EXISTS in hana SQL query - sql

I have this query code:
IF EXISTS (
SELECT
*
FROM sys.objects
WHERE object_id =
OBJECT_ID(N'[dbo].[BAL_WMS_STAGING]')
AND type in (N'U')
)
DROP TABLE
[dbo].[BAL_WMS_STAGING]
GO
CREATE TABLE
I am trying to use this statement to query an SAP Hana Database. The beginning of the query IF EXISTS keeps throwing an error, I assume that this means that this keyword does not exist in Hana SQL syntax. Does anyone know how to do an IF EXISTS check in Hana, as I am unable to find any answer online.

If EXISTS is a non-standard syntax that HANA doesn't support.
As an alternative you can query the catalog and write a IF...THEN statement in SQLScript.

An alternative to using IF EXISTS could be something like this:
SELECT *
FROM sys.objects
WHERE object_id = (
CASE
WHEN EXISTS (
SELECT object_id
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[BAL_WMS_STAGING]')
AND type IN (N'U'))
THEN (
SELECT object_id
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[BAL_WMS_STAGING]')
AND type IN (N'U'))
ELSE
NULL
END
)
AND type IN (N'U')

SQLScript does not have IF EXIST condition.
But same logic can be achieved by creating a variable (flag) that is initialized by your first query.
You dont need to select all the columns. You can select as an example object_id.
flag = '';
SELECT object_id INTO flag FROM sys.objects
WHERE object_id =
OBJECT_ID(N'[dbo].[BAL_WMS_STAGING]')
AND type in (N'U');
IF flag != '' THEN
DROP TABLE [dbo].[BAL_WMS_STAGING]
END IF;

Related

Table "already exists" after dropping with if exists

I got a pretty complex SQL that finally forced me to use a temp table to work around.
Essentially it looks like this:
;IF EXISTS(SELECT * FROM sys.tables WHERE SCHEMA_NAME(schema_id) LIKE 'dbo' AND name like '#MYTEMPTABLE')
DROP TABLE #MYTEMPTEBLE;
WITH cte AS ...
SELECT * INTO #MYTEMPTABLE FROM cte
SELECT * FROM #MYTEMPTABLE WHERE [conditions]
DROP TABLE #MYTEMPTABLE;
However, I get an error message saying an object with the name #MYTEMPTABLE already exists in the database after a call with an error (which is rather likely if the customer/tester screws up some data).
It might DROP TABLE fail on your check condition, it might check from TempDB.INFORMATION_SCHEMA.COLUMNS table instead of sys.tables table
SELECT * FROM TempDB.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME IN (
SELECT NAME
FROM TempDB.SYS.TABLES
WHERE OBJECT_ID=OBJECT_ID('TempDB.dbo.#MYTEMPTEBLE')
);
sqlfiddle
If your SQL server version was higher than 2016, you can try to use DROP TABLE IF EXISTS
DROP TABLE IF EXISTS #MYTEMPTEBLE;
WITH cte AS ...
SELECT * INTO #MYTEMPTABLE FROM cte
SELECT * FROM #MYTEMPTABLE WHERE [conditions]
if your SQL server version didn't support that, you can check OBJECT_ID IS NOT NULL which represnt temp table exists in your system
IF OBJECT_ID('TempDB..#MYTEMPTEBLE') IS NOT NULL
DROP TABLE #MYTEMPTEBLE;

Drop indexes or alter

I am trying to drop pk constraint and drop index on the target table in informatica, these below statements are working first time successfully.
IF EXISTS (SELECT Name FROM sysindexes WHERE Name = 'xyz')
DROP INDEX [xyz] ON [dbo].[Table_Name];
IF EXISTS (SELECT Name FROM sysindexes WHERE Name = 'xyz')
ALTER TABLE [dbo].[Table_Name] DROP CONSTRAINT [xyz];
But if I run the same query a second time it is giving an error:
Cannot drop the index 'dbo.Table_Name.xyz', because it does not exist or you do not have permission
I need an If ... Else statement syntax like if exists drop else end or success something.
The likely cause for this is that you might have more than one index named xyz on your database. Your IF EXISTS SELECT statement is not taking into consideration which table xyz is on.
You can check for this condition yourself by running the select statement by itself.
Try changing your query to the following to limit the scope:
If Exists
(
Select *
From sys.indexes
Where name = 'xyz'
And Object_Id = Object_Id('dbo.Table_Name')
)
Drop Index xyz On dbo.Table_Name;
One way to get around this issue is to trick the parser:
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE SCHEMA_NAME = 'dbo' AND TABLE_NAME = 'Table_Name' AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND CONSTRAINT_NAME = 'xyz')
BEGIN
EXEC('ALTER TABLE [dbo].[Table_Name] DROP CONSTRAINT [xyz]')
END

How can I check if the table behind a synonym exists

I'm trying to create a simple script to dump the results of a complex view out into a table for reporting. I have used synonyms to simplify tweaking the view and table names.
The idea is that the user of the script can put the name of the view they want to use as the source, and the name of the target reporting table in at the start and away they go. If the table doesn't exist then the script should create it. If the table already exists then the script should only copy the records from the view which aren't already in the table over.
The script below covers all those requirements, but I can't find a nice way to check if the table behind the synonym already exists:
CREATE SYNONYM SourceView FOR my_view
CREATE SYNONYM TargetReportingTable FOR my_table
-- Here's where I'm having trouble, how do I check if the underlying table exists?
IF (SELECT COUNT(*) FROM information_schema.tables WHERE table_name = TargetReportingTable) = 0
BEGIN
-- Table does not exists, so insert into.
SELECT * INTO TargetReportingTable FROM SourceView
END
ELSE
BEGIN
-- Table already exists so work out the last record which was copied over
-- and insert only the newer records.
DECLARE #LastReportedRecordId INT;
SET #LastReportedRecordId = (SELECT MAX(RecordId) FROM TargetReportingTable)
INSERT INTO TargetReportingTable SELECT * FROM SourceView WHERE RecordId > #LastReportedRecordId
END
DROP SYNONYM SourceView
DROP SYNONYM TargetReportingTable
I know I could just get the user of the script to copy the table name into the 'information_schema' line as well as into the synonym at the top, but that leaves scope for error.
I also know I could do something filthy like put the table name into a variable and blat the SQL out as a string, but that makes me feel a bit sick!
Is there a nice elegant SQL way for me to check if the table behind the synonym exists? Or a totally different way to solve to problem?
Not the most elegant of solutions, but you could join the sys.synonyms table to the sys.tables table to check whether the table exists.
If the table does not exist, the join will fail and you will get 0 rows (hence IF EXISTS will be false). If the table does exist, the join will success and you will get 1 row (and true):
IF EXISTS( SELECT *
FROM sys.synonyms s
INNER JOIN sys.tables t ON REPLACE(REPLACE(s.base_object_name, '[', ''), ']', '') = t.name
WHERE s.name = 'TargetReportingTable')
BEGIN
-- Does exist
END
ELSE
BEGIN
-- Does not exist
END
Replace 'TargetReportingTable' with whichever synonym you wish to check.
The above solutions did not work for me if the synonym referenced another database. I recently discovered the function [fn_my_permissions] which is useful for showing permissions for a specific database object, so I figure this could be used as follows:
IF EXISTS
(
select *
from sys.synonyms sy
cross apply fn_my_permissions(sy.base_object_name, 'OBJECT')
WHERE sy.name = 'TargetReportingTable'
)
print 'yes - I exist!'
Late to the party, I have created a query to test out the existence of Synonyms and share with you.
DECLARE #Synonyms table
(
ID int identity(1,1),
SynonymsDatabaseName sysname,
SynonymsSchemaName sysname,
SynonymsName sysname,
DatabaseName nvarchar(128),
SchemaName nvarchar(128),
ObjectName nvarchar(128),
Remark nvarchar(max),
IsExists bit default(0)
)
INSERT #Synonyms (SynonymsDatabaseName, SynonymsSchemaName, SynonymsName, DatabaseName, SchemaName, ObjectName)
SELECT
DB_NAME() AS SynonymsDatabaseName,
SCHEMA_NAME(schema_id) AS SynonymsSchemaName,
name AS SynonymsName,
PARSENAME(base_object_name,3) AS DatabaseName,
PARSENAME(base_object_name,2) AS SchemaName,
PARSENAME(base_object_name,1) AS ObjectName
FROM sys.synonyms
SET NOCOUNT ON
DECLARE #ID int = 1, #Query nvarchar(max), #Remark nvarchar(max)
WHILE EXISTS(SELECT * FROM #Synonyms WHERE ID = #ID)
BEGIN
SELECT
#Query = 'SELECT #Remark = o.type_desc FROM [' + DatabaseName + '].sys.objects o INNER JOIN sys.schemas s ON o.schema_id = s.schema_id WHERE s.name = ''' + SchemaName + ''' AND o.name = ''' + ObjectName + ''''
FROM #Synonyms WHERE ID = #ID
EXEC sp_executesql #Query, N'#Remark nvarchar(max) OUTPUT', #Remark OUTPUT;
UPDATE #Synonyms SET IsExists = CASE WHEN #Remark IS NULL THEN 0 ELSE 1 END, Remark = #Remark WHERE ID = #ID
SELECT #ID += 1, #Remark = NULL
END
SELECT * FROM #Synonyms
You can do this with dynamic SQL:
-- create synonym a for information_schema.tables
create synonym a for b
declare #exists int = 1;
begin try
exec('select top 0 * from a');
end try
begin catch
set #exists = 0;
end catch
select #exists;
This doesn't work with non-dynamic SQL, because the synonym reference is caught at compile-time. That means that the code just fails with a message and is not caught by the try/catch block. With dynamic SQL, the block catches the error.
You can test if Synonym exists in your database using the Object_Id function avaliable in SQL Server
IF OBJECT_ID('YourDatabaseName..YourSynonymName') IS NOT NULL
PRINT 'Exist SYNONYM'
ELSE
PRINT 'Not Exist SYNONYM'
Another simpler solution:
IF (EXISTS (SELECT * FROM sys.synonyms WHERE NAME ='mySynonymName'))
BEGIN
UPDATE mySynonymName
SET [Win] = 1
END
In this case, I do database setup first. I drop all Synonyms in my database (database1) first, then run a SPROC to create synonyms for all tables in the destination database(database2).
Some SPROCS in database1 call on tables in DB2. If table doesnt exist in DB2 the SPROC fails. If table doesnt exist in DB2, the synonmy is not automatically created on database setup. So I just use the above to check if the Synonym exist, and skip that part of the SPROC if the Synonym is not present.

Drop table if exist with similar name in two schema

I use this command to drop a table in sql-server 2008
IF EXISTS(SELECT name FROM [DBName]..sysobjects WHERE name = N'TableName' AND xtype='U')
DROP TABLE [DBName].[SchemaName].[TableName];
But now I have 2 tables with same name in different schema:
[DBName].[Schema1].[Members]
And
[DBName].[Schema2].[Members]
So, what is your suggestion for check if exist this tables? How can I check table names with schema?
UPDATE:
OK, there is 3 different answers and all of them worked, so I don't know which one is better, does any one know about use object_id or sys.tables?
IF EXISTS(
SELECT *
FROM [DBName].sys.tables t
JOIN [DBName].sys.schemas s
ON t.SCHEMA_ID = s.schema_id
WHERE
t.name = N'TableName' AND t.type='U'
AND s.NAME = 'SchemaName'
)
DROP TABLE [DBName].[SchemaName].[TableName];
Update:
object_id in sys.tables is the same as object_id in sysobjects for the same table. And is completely the same as function OBJECT_ID returns for the same table name. See the following illustrating examples.
So, you may simplify the query:
IF exists
(
SELECT *
FROM DBName.sys.tables
WHERE object_id = OBJECT_ID('[DBName].[SchemaName].[TableName]')
AND type = 'U'
)
DROP TABLE [DBName].[SchemaName].[TableName];
or in this way:
IF exists
(
SELECT *
FROM DBName.sys.objects
WHERE object_id = OBJECT_ID('[DBName].[SchemaName].[TableName]')
AND type = 'U'
)
DROP TABLE [DBName].[SchemaName].[TableName];
or for sql2000-styled tables:
IF exists
(
SELECT *
FROM DBName..sysobjects
WHERE object_id = OBJECT_ID('[DBName].[SchemaName].[TableName]')
AND xtype = 'U'
)
DROP TABLE [DBName].[SchemaName].[TableName];
Use this:
IF EXISTS
(
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[DBName].[Schema1].[Member]')
AND type in (N'U')
)
PRINT 'Yes'
ELSE
PRINT 'No';
Don't use sysobjects. Use the modern system views in the sys schema (introduced in 2005):
select * from sys.tables
where
schema_id = SCHEMA_ID('Schema1') and
name='tablename'
As soon as you have one "modern" schema in a 2005 or later database, you cannot reliably use sysobjects to match with schemas. If you only have "old" schemas (objects belonging to users and roles), you may be able to query based on user_id.
Wouldn't it be simplest just to:
IF object_id('[schema].[table]') > 0
DROP TABLE [schema].[table]
For non existent tables object_id() returns NULL
For some system tables it returns a negative int

How to identify whether the table has identity column

I want to find out whether the table has an identity column or not. Table is unknown to me. I have not done the structure of the table. Using Query?
I am using Sql Server Compact Edition.
IF (OBJECTPROPERTY(OBJECT_ID('TABLE_NAME'), 'TableHasIdentity') = 1)
ObjectProperty is available starting sql server 2008 Reference:
OBJECTPROPERTY
This query returns a table's identity column name:
CREATE PROCEDURE dbo.usp_GetIdentity
#schemaname nvarchar(128) = 'dbo'
,#tablename nvarchar(128)
AS
BEGIN
SELECT OBJECT_NAME(OBJECT_ID) AS TABLENAME,
NAME AS COLUMNNAME,
SEED_VALUE,
INCREMENT_VALUE,
LAST_VALUE,
IS_NOT_FOR_REPLICATION
FROM SYS.IDENTITY_COLUMNS
WHERE OBJECT_NAME(OBJECT_ID) = #tablename
AND OBJECT_SCHEMA_NAME(object_id) = #schemaname
END
Then form the code side.
Call this stored procedure using the datareader role, then check datareader.hasrows(). If the condition value is true (1), then the table has identity column if set. If not then it doesn't have an identity column.
I know it's long time ago but i found this helpful
try this :
IF EXISTS (SELECT * from syscolumns where id = Object_ID(#TABLE_NAME) and colstat & 1 = 1)
BEGIN
-- Do your things
END
Any of the below queries can be used to check if an Identity Column is present in the table
1)
SELECT *
FROM sys.identity_columns
WHERE OBJECT_NAME(object_id) = 'TableName'
2)
SELECT *
FROM sys.identity_columns
WHERE object_id = (
SELECT id
FROM sysobjects
WHERE name = 'TableName'
)
I would just like to add this option as well as I think it is the simplest
SELECT COLUMNPROPERTY(OBJECT_ID('TableName'),'ColumnName','isidentity')
One way to do this would be to make use of the stored procedure sp_help. I.e:
sp_help MyTable
This will return a DataSet that has all the information you would need on the table. There is a specific Table that has information on identities.
I.e:
If it does not contain an identity field, the Identity column will say: "No identity column defined".
#Pranay: he said Compact Edition. Stored procedures aren't supported, and there is no sys.anything.
This is the call:
SELECT Count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE AUTOINC_INCREMENT IS NOT NULL AND TABLE_NAME='this_table'
It will return either 1 (true) or 0 (false).
...
declare #tblhasIdentCol bit = IF (IDENT_CURRENT( #dbName +'.'+ #schemaName +'.'+ #tableName ) IS NOT NULL , 1 , 0 )
You get numeric value if table has identity
Very simple answer would be to run this:
SELECT IDENT_CURRENT('TABLE-NAME')
This would give max value of identity column if exists, if the column doesn't exist, it gives 1 as result.
Based on max value, you can identify which column is having that and determine the identity column.
This the query that get u all the tableNames, columnnames of the table, and is_identity or not in the selected database
SELECT
sys.columns.name
, sys.tables.name
, is_identity
FROM sys.columns
INNER JOIN sys.tables ON sys.tables.object_id = sys.columns.object_id
AND sys.columns.is_identity = 1
CREATE FUNCTION dbo.fnTableHasIdentity(#Tbl sysname)
RETURNS TINYINT
BEGIN
RETURN OBJECTPROPERTY(OBJECT_ID(#Tbl), 'TableHasIdentity')
END
--As simple as that!
select t.name as TableName,c.name as ColumnName
from sys.identity_columns c
inner join sys.tables t on c.object_id = t.object_id
where t.name = 'TableName'
If you like me, needed to be able to do this for tables in an arbitrary database, then I found the following solution:
IF EXISTS (
SELECT 1
FROM [database name].sys.identity_columns AS id_col
INNER JOIN [database name].sys.objects
ON objects.object_id = id_col.object_id
INNER JOIN [database name].sys.schemas
ON schemas.schema_id = objects.schema_id
AND schemas.name = 'schema name'
WHERE OBJECT_NAME(id_col.object_id, DB_ID('database name')) = 'table name'
) SELECT 1 ELSE SELECT 0
you can get the 1 or 0 Boolean Form if the current table has identity Columns by using this
SELECT Count(Column_ID) FROM sys.identity_columns WHERE OBJECT_NAME(object_id) = 'tableName'
One way to list all Tables with their identity column if it exists
to get you desired table add at the end of the filter "and o.name='TableName'"
where Tbale Nam is the table you are looking for
SELECT o.[Name][TableName],i.[name][IdentityColName] FROM
sys.objects o
left outer join sys.identity_columns i on i.object_id=o.object_id
where o.type='U'