MS SQL IF Statement Executing IF and ELSE Blocks - sql

All, I have the following query
IF NOT EXISTS (SELECT name
FROM sys.databases
WHERE name = N'Report')
BEGIN
DECLARE #DatabasePath NVARCHAR(1000);
SET #DatabasePath = (SELECT ResultMessage + '\'
FROM [Admin]..[Process]);
EXEC ispCREATEDB N'Report', #DatabasePath, N'10MB', N'20%'
END
ELSE
BEGIN
IF EXISTS (SELECT *
FROM Report.sys.objects
WHERE name = N'FatalErrSumm' AND type = N'U')
BEGIN
DROP TABLE [Report]..[FatalErrSumm];
CREATE TABLE [Report]..[FatalErrSumm]
(
[MDF] NVARCHAR(255) NULL,
[Error] INT NULL,
);
END
END
This checks if Report exists from a different databse; if it does not exist it creates it, if it does, it checks if table FatalErrSumm exists and if it does it drops and recreates it.
The problems is that it seems to be executing both possiblities of the IF NOT EXISTS block and giving the error
Msg 2702, Level 16, State 2, Line 24
Database 'Report' does not exist.
when the database Report does not exist. So it should never be entering the ELSE block, however it seems to be. This is very basic stuff, but I cannot for the life of me spot the error, What am I doing wrong here?
Thanks for your time.

You should bypass it using a dynamic sql
IF NOT EXISTS (SELECT name
FROM sys.databases
WHERE name = N'Report')
BEGIN
DECLARE #DatabasePath NVARCHAR(1000);
SET #DatabasePath = (SELECT ResultMessage + '\'
FROM [Admin]..[Process]);
EXEC ispCREATEDB N'Report', #DatabasePath, N'10MB', N'20%'
END
ELSE IF DB_ID('Report') IS NOT NULL
EXEC
(
'BEGIN
IF EXISTS (SELECT *
FROM Report.sys.objects
WHERE name = N''FatalErrSumm'' AND type = N''U'')
BEGIN
DROP TABLE [Report]..[FatalErrSumm];
CREATE TABLE [Report]..[FatalErrSumm]
(
[MDF] NVARCHAR(255) NULL,
[Error] INT NULL,
);
END
END'
);

I think dynamic sql is the good solution for that. because in compile time compiler checked that the database "report" is not exist in you server.

If the report is offline I think this failes, check if the database is online /attached. There is flag for this in the sys.databases table.
Also do not put your statements in the ELSE. If you enter the 'THEN' part you create the database. After that check if it is created. Than ALWAYS check for you FATALERRSUMM table and not from the IF.
pseudo code:
if (not exists database) -- watch it not exists is really NOT EXISTS not just not online
create the database
if (exists database and not online)
put online the database
if (not exists database or not online database)
throw error
if (exists table fatalerrsum)
drop table
create table

Related

Create database if db does not exist

I want to make SQL Server script for creating database if it does not exist.
IF NOT EXISTS(SELECT * FROM sys.databases WHERE name = 'DataBase')
BEGIN
CREATE DATABASE DataBase
USE DataBase
CREATE TABLE TableName (
Id INT PRIMARY KEY IDENTITY (1, 1),
Name VARCHAR(100)
)
--more tables here
--some procedures here too
END
From code above I'm getting this error:
Msg 911, Level 16, State 1, Line 5
Database 'DataBase' does not exist. Make sure that the name is entered correctly.
How to make database with tables and procedures when database does not exist? I want to make it in one query.
Could you check the following script :
IF NOT EXISTS(SELECT * FROM sys.databases WHERE name = 'DataBase')
BEGIN
CREATE DATABASE [DataBase]
END
GO
USE [DataBase]
GO
--You need to check if the table exists
IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='TableName' and xtype='U')
BEGIN
CREATE TABLE TableName (
Id INT PRIMARY KEY IDENTITY (1, 1),
Name VARCHAR(100)
)
END
Obviously you have to start with (and mind the GO here):
USE master
GO
But you have to do it like this:
IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = 'MyTestDataBase')
BEGIN
CREATE DATABASE MyTestDataBase;
END;
GO
Mind the GO again. If you don't use GO SSMS (or any other client) will still think your batch is not completed, your database is still not created and therefore not available for further use, and you get the error message you posted.
Now you can start using your just created database with:
USE MyTestDataBase;
GO
Again, mind the GO statement. In this case it is inadmissible because it is not possible to combine CREATE DATABASE and CREATE TABLE statements in one batch. So after the GO continue with:
IF OBJECT_ID('MyTestTable', 'U') IS NULL
BEGIN
CREATE TABLE dbo.MyTestTable
(
Id INT PRIMARY KEY IDENTITY(1, 1)
, Name VARCHAR(100)
);
END;
As already mentioned by others it is good practice to check if every table exists and do a create action if it doesn't and alter action if it does (or just do nothing). But if you really don't want to check if each table exists, for instance when you are sure you need to start from scratch, you could start with dropping the database if it exists:
IF EXISTS (SELECT * FROM sys.databases WHERE name = 'MyTestDataBase')
BEGIN
DROP DATABASE MyTestDataBase;
END;
CREATE DATABASE MyTestDataBase;
GO
You can try this.
IF NOT EXISTS (
SELECT *
FROM sys.databases
WHERE name = 'DataBase'
)
BEGIN
CREATE DATABASE [DataBase]
END
GO
USE [DataBase]
GO
IF NOT EXISTS (
SELECT 1
FROM sys.tables
WHERE name = 'TableName'
AND type = 'U'
)
BEGIN
CREATE TABLE TableName (
Id INT PRIMARY KEY IDENTITY(1, 1)
,Name VARCHAR(100)
)
END

SQL Server - Check column if exists >> rename and change type

SQL Server:
Check column if exists when
If True : (Change/Modify) column_name and dataType
If False : Create
Schema name : Setup
Code:
IF EXISTS (SELECT 1 FROM sys.columns
WHERE Name = N'bitIntialBalance'
AND Object_ID = Object_ID(N'Setup.LeaveVacationsSubType'))
BEGIN
ALTER TABLE [Setup].[LeaveVacationsSubType]
ALTER COLUMN intIntialBalance INT NULL;
EXEC sp_RENAME 'Setup.LeaveVacationsSubType.bitIntialBalance', 'intIntialBalance', 'COLUMN';
--ALTER TABLE [Setup].[LeaveVacationsSubType] MODIFY [intIntialBalance] INT; not working
END
GO
IF NOT EXISTS(SELECT 1 FROM sys.columns
WHERE Name = N'intIntialBalance'
AND Object_ID = Object_ID(N'Setup.LeaveVacationsSubType'))
BEGIN
ALTER TABLE [Setup].[LeaveVacationsSubType]
ADD intIntialBalance INT NULL;
END
GO
If I guess correctly, the problem is that query plan is made for the whole script, and SQL Server also checks that it can actually perform all the operations, even if it is inside an if statement. That's why you'll get an error, even if in the reality that statement would never be executed.
One way to get around this issue is to make all those statements dynamic, something like this:
execute ('ALTER TABLE [Setup].[LeaveVacationsSubType] MODIFY [intIntialBalance] INT')

Temp table already exists

Hi I have a temporary table in which I am trying to insert records based on a where condition but it throws an error that it already exists.
I have tried to change the names but that is not the issue as the temporary tables are delete when the session ends.
I think I am writing the query right.
SELECT [Name]
INTO #TEMP_REJECT
FROM #TEMP_VALIDATION
WHERE Name = #Name
I am trying to insert #TEMP_REJECT FROM #TEMP_VALIDATION
Error message
"There is already an object named '#TEMP_REJECT' in the database."
Please suggest.
Thank you for your help.
R
SQL Server won't tell you that a table doesn't exist if it doesn't.
I suggest that you add
IF OBJECT_ID('tempdb..#TEMP_REJECT') IS NOT NULL
DROP TABLE #TEMP_REJECT
in front of your select statement. This guarantees that the temp table won't exist when the select is executed.
So your statement becomes
IF OBJECT_ID('tempdb..#TEMP_REJECT') IS NOT NULL
DROP TABLE #TEMP_REJECT
SELECT [Name]
INTO #TEMP_REJECT
FROM #TEMP_VALIDATION
WHERE Name = #Name
This answer will help you :
https://stackoverflow.com/a/8560644/3635715
To make short : SELECT INTO creates table then insert records.
INSERT INTO only insert the records.
So in your case, since #TEMP_REJECT already exists, SELECT INTO is rejected because it cannot create the table again, so you have to use INSERT INTO after first SELECT INTO.
IF OBJECT_ID('tempdb..#TEMP_REJECT') IS NOT NULL
BEGIN
INSERT INTO #TEMP_REJECT
SELECT [Name]
FROM #TEMP_VALIDATION
WHERE Name = #Name
END
ELSE
BEGIN
SELECT [Name]
INTO #TEMP_REJECT
FROM #TEMP_VALIDATION
WHERE Name = #Name
END
References :
INTO Clause
INSERT Clause
Try checking before inserting
if object_id('tempdb..#TEMP_REJECT') is not null
drop table #TEMP_REJECT
SELECT [Name]
INTO #TEMP_REJECT
FROM #TEMP_VALIDATION
WHERE Name = #Name
if SQL says,there is temp table,there must be a table prior to your insert
I've noticed that I get the same error when I am working consecutively through the same SQL Server tab/file.
For example, I have a large SQL file that I use to execute a series of updates using temp tables. When I execute it consecutively, it errors out complaining that my #tempTable already exists (even if I use a "if this table exists, drop it" statement as DeanOC describes).
Exiting out of the file/tab between consecutive runs resolves the issue.
If this poses an issue for your use case, I'd suggest bundling your statements in a stored proc and implementing DeanOC's drop logic therein.

Add column to existing table and default value to another column without dynamic sql

For Sql Server 2005 and 2008 I want to check if a column already exists on a given table and create it if it doesn't. This new column should have a default value of an ExistingColumn. Currently I need to use dynamic sql to fill the new column because sql server will complain of a syntax error.
Here is the current sql server code:
IF NOT EXISTS (SELECT TOP 1 1 FROM sys.columns WHERE [name] = N'NewColumn' AND OBJECT_ID = OBJECT_ID(N'ExistingTable'))
BEGIN
ALTER TABLE [dbo].[ExistingTable] ADD [NewColumn] VARCHAR(50) NULL;
exec sp_executesql N'UPDATE [dbo].[ExistingTable] SET NewColumn = ExistingColumn'
ALTER TABLE [dbo].[ExistingTable] ALTER COLUMN [NewColumn] VARCHAR(50) NOT NULL
END
GO
Is there any other way to solve this problem without resorting to dynamic sql?
Since you're creating the column regardless, you could do two separate batches.
IF NOT EXISTS (SELECT TOP 1 1 FROM sys.columns WHERE [name] = N'NewColumn' AND OBJECT_ID = OBJECT_ID(N'ExistingTable'))
BEGIN
ALTER TABLE [dbo].[ExistingTable] ADD [NewColumn] VARCHAR(50) NULL;
END
GO
IF EXISTS (SELECT TOP 1 1 FROM sys.columns WHERE [name] = N'NewColumn' AND OBJECT_ID = OBJECT_ID(N'ExistingTable'))
BEGIN
IF EXISTS (SELECT 1 FROM [dbo].[ExistingTable] WHERE NewColumn IS NULL)
BEGIN
UPDATE [dbo].[ExistingTable] SET NewColumn = ExistingColumn
ALTER TABLE [dbo].[ExistingTable] ALTER COLUMN [NewColumn] VARCHAR(50) NOT NULL
END
END
GO
SQL Server is parsing your statement before your ALTER runs, and saying "Hey, no such column." The parser doesn't understand IF and other branching and can't follow the sequence of events when you mix DDL and DML - or predict the sequence the events will take and what branching will happen at runtime.
Deferred name resolution allows you to access objects that don't exist yet, but not columns that don't exist yet on objects that do.
So, dynamic SQL seems like the way you'll have to do it.

Is it possible to tell SSMS not to check if a column exists in a t-sql script?

I tried to google it, but din't find a way
I have a t-sql script that adds a new column to a table, then fills that columns with values depending on some other columns in the same table and finally removes some columns. This all works fine.
The problem occures when I want to run the script again. I have a if clause that checks if the missing columns exists, but SSMS still complains and displays error messaged even though the code inside the if clause if not run. The script must be able to run more then once, and I don't want the error messages to be displayed!
In code (obviously test code, don't want to dump production code here...):
create table test (
Name text,
Switch int,
ValueA int,
ValueB int)
go
insert into test values ('Name', 0, 5, 10)
if not exists (select 1 from INFORMATION_SCHEMA.COLUMNS
where COLUMN_NAME = 'ValueC' and TABLE_NAME = 'test')
begin
alter table test
add ValueC int
end
go
-- This batch rasies error when run more then once!
if exists (select 1 from INFORMATION_SCHEMA.COLUMNS
where COLUMN_NAME = 'ValueA' and TABLE_NAME = 'test')
begin
update test
set ValueC = (select case Switch
when 0 then (select (ValueA - ValueB))
when 1 then (select (ValueB - ValueA))
end)
end
go
if exists (select 1 from INFORMATION_SCHEMA.COLUMNS
where COLUMN_NAME = 'ValueA' and TABLE_NAME = 'test')
begin
alter table test drop column ValueA
end
go
select * from test
--Name 0 10 -5
Here is the error message:
Msg 207, Level 16, State 1, Line 6
Invalid column name 'ValueA'.
Msg 207, Level 16, State 1, Line 7
Invalid column name 'ValueA'.
Cheers
--Jocke
Yes it is possible without dynamic SQL but with a bit of a kludgey workaround. I would just use EXEC for this.
The behaviour in SQL 2000 is explained here
Erland Sommarskog mentions "once all tables in a query exist, SQL Server performs full checks on the query."
So by adding a no-op reference in the query to a table that doesn't exist compilation can be deferred. With this adjustment the script below can be run multiple times without getting the error.
insert into test values ('Name', 0, 5, 10)
if not exists (select 1 from INFORMATION_SCHEMA.COLUMNS
where COLUMN_NAME = 'ValueC' and TABLE_NAME = 'test')
begin
alter table test
add ValueC int
end
go
create table #dummy
(i int)
-- This batch raised error when run more then once!
if exists (select 1 from INFORMATION_SCHEMA.COLUMNS
where COLUMN_NAME = 'ValueA' and TABLE_NAME = 'test')
begin
update test
set ValueC = (select case Switch
when 0 then (select (ValueA - ValueB))
when 1 then (select (ValueB - ValueA))
end) where not exists(select * from #dummy)
end
drop table #dummy
go
if exists (select 1 from INFORMATION_SCHEMA.COLUMNS
where COLUMN_NAME = 'ValueA' and TABLE_NAME = 'test')
begin
alter table test drop column ValueA
end
go
select * from test
--Name 0 10 -5
why don't you jsut use a temp table or variable table, add the last column to the declaration, and then you wouldn't have this problem?
I had this exact problem and the only thing that worked for me was to save the script. Close it. Then open it again in and run it in the query window.
Also, it looks like you have the proper GOs, but I found that if I was missing the GO after the check to add the column then not even re-opening the script worked.
Bit late to the party but I ran into this same scenario when trying to do conditional checks based on what version of SQL Server. I took the EXEC route mentioned above. In the below example as inline T-SQL, the SELECT against sys.tables would result in an invalid column name if ran on an earlier version of SQL Server that didn't have the column available.
To work around it, I put the SQL inside a variable and EXEC() it as part of a INSERT INTO to populate a table variable.
DECLARE #Status TABLE (
Result bit
)
DECLARE #Result bit
IF #SQLVer >= 11
SET #SQL='SELECT 1 FROM sys.tables WHERE object_id=' + CONVERT(varchar,#CurrTableObjID) + ' AND is_filetable=1'
DELETE FROM #Status
INSERT INTO #Status
EXEC (#SQL)
SELECT #Result=Result FROM #Status
IF IsNULL(#Result,0) = 1
BEGIN
PRINT 'Table ' + #CurrSchemaName + '.' + #CurrTableName + ' is a filetable'
SET #BadTables=1
END