IF Database not Exists then Truncate command giving error in SQL SERVER 2016 but its working fine in lower version in SQL Server .. please suggest - sql

IF EXISTS (SELECT 1 FROM Master..SysDatabases WHERE [name] = 'abcd')
BEGIN
TRUNCATE TABLE abcd.dbo.ascf
END

As a one of the workarounds:
IF EXISTS (SELECT 1 FROM Master..SysDatabases WHERE [name] = 'abcd')
BEGIN
EXEC ('TRUNCATE TABLE abcd.dbo.ascf')
END
Lowering of compatibility level to SQL 2008 - SQL2014 will not help.

Related

How to copy a table from a linked server into the main database only on the condition that the table does not already exist?

I am using SQL Server 2012 and I have the following T-SQL query:
USE MyDatabase
INSERT INTO [Table1]
SELECT *
FROM [xxx.xx.x.xx].[xxx].[dbo].[Table1]
I would like to modify this query so that it copies Table1 into MyDatabase only if that table does not already exist in MyDatabase.
I've had a look here but I can't figure out how to migrate the solutions into my problem: Check if table exists in SQL Server
How can I achieve this?
This should do it:
IF (NOT EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'Table1'))
BEGIN
INSERT INTO [Table1]
SELECT *
FROM [xxx.xx.x.xx].[xxx].[dbo].[Table1]
END
More details and approaches you can read here:
Check if table exists in SQL Server

MS SQL IF Statement Executing IF and ELSE Blocks

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

Efficient SQL test query or validation query that will work across all (or most) databases

Many database connection pooling libraries provide the ability to test their SQL connections for idleness. For example, the JDBC pooling library c3p0 has a property called preferredTestQuery, which gets executed on the connection at configured intervals. Similarly, Apache Commons DBCP has validationQuery.
Many example queries I've seen are for MySQL and recommend using SELECT 1; as the value for the test query. However, this query doesn't work on some databases (e.g. HSQLDB, for which SELECT 1 expects a FROM clause).
Is there a database-agnostic query that's equivalently efficient but will work for all SQL databases?
Edit:
If there's not (which seems to be the case), can somebody suggest a set of SQL queries that will work for various database providers? My intention would be to programmatically determine a statement I can use based on my database provider configuration.
After a little bit of research along with help from some of the answers here:
SELECT 1
H2
MySQL
Microsoft SQL Server (according to NimChimpsky)
PostgreSQL
SQLite
Hive
SELECT 1 FROM DUAL
Oracle
SELECT 1 FROM any_existing_table WHERE 1=0
or
SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS
or
CALL NOW()
HSQLDB (tested with version 1.8.0.10)
Note: I tried using a WHERE 1=0 clause on the second query, but it didn't work as a value for Apache Commons DBCP's validationQuery, since the query doesn't return any rows
VALUES 1 or SELECT 1 FROM SYSIBM.SYSDUMMY1
Apache Derby (via daiscog)
SELECT 1 FROM SYSIBM.SYSDUMMY1
DB2
select count(*) from systables
Informix
If your driver is JDBC 4 compliant, there is no need for a dedicated query to test connections. Instead, there is Connection.isValid to test the connection.
JDBC 4 is part of Java 6 from 2006 and you driver should support this by now!
Famous connection pools, like HikariCP, still have a config parameter for specifying a test query but strongly discourage to use it:
🔠connectionTestQuery
If your driver supports JDBC4 we strongly
recommend not setting this property. This is for "legacy" databases
that do not support the JDBC4 Connection.isValid() API. This is the
query that will be executed just before a connection is given to you
from the pool to validate that the connection to the database is still
alive. Again, try running the pool without this property, HikariCP
will log an error if your driver is not JDBC4 compliant to let you
know. Default: none
Unfortunately there is no SELECT statement that will always work regardless of database.
Most databases support:
SELECT 1
Some databases don't support this but have a table called DUAL that you can use when you don't need a table:
SELECT 1 FROM DUAL
MySQL also supports this for compatibility reasons, but not all databases do. A workaround for databases that don't support either of the above is to create a table called DUAL that contains a single row, then the above will work.
HSQLDB supports neither of the above, so you can either create the DUAL table or else use:
SELECT 1 FROM any_table_that_you_know_exists_in_your_database
The jOOQ manual's section about the DUAL table lists the following for jOOQ's select(inline(1)) query:
-- Access
SELECT 1 FROM (SELECT count(*) dual FROM MSysResources) AS dual
-- BigQuery, CockroachDB, Exasol, H2, Ignite, MariaDB, MySQL, PostgreSQL,
-- Redshift, Snowflake, SQLite, SQL Server, Sybase ASE, Vertica
SELECT 1
-- MemSQL, Oracle
SELECT 1 FROM DUAL
-- CUBRID
SELECT 1 FROM db_root
-- Db2
SELECT 1 FROM SYSIBM.DUAL
-- Derby
SELECT 1 FROM SYSIBM.SYSDUMMY1
-- Firebird
SELECT 1 FROM RDB$DATABASE
-- HANA, Sybase SQL Anywhere
SELECT 1 FROM SYS.DUMMY
-- HSQLDB
SELECT 1 FROM (VALUES(1)) AS dual(dual)
-- Informix
SELECT 1 FROM (SELECT 1 AS dual FROM systables WHERE (tabid = 1)) AS dual
-- Ingres, Teradata
SELECT 1 FROM (SELECT 1 AS "dual") AS "dual"
I use this one:
select max(table_catalog) as x from information_schema.tables
to check connection and ability to run queries (with 1 row as result) for postgreSQL, MySQL and MSSQL.
I use
Select COUNT(*) As X From INFORMATION_SCHEMA.SYSTEM_USERS Where 1=0
for hsqldb 1.8.0
For tests using select count(*), it should be more efficient to use select count(1) because * can cause it to read all the column data.
select 1 would work in sql server, not sure about the others.
Use standard ansi sql to create a table and then query from that table.
Assuming the OP wants a Java answer:
As of JDBC3 / Java 6 there's the isValid() method which should be used rather than inventing one's own method.
The implementer of the driver is required to execute some sort of query against the database when this method id called. You - as a mere JDBC user - do not have to know or understand what this query is. All you have to do is to trust that the creator of the JDBC driver has done his/her work properly.
How about
SELECT user()
I use this before.MySQL, H2 is OK, I don't know others.
Just found out the hard way that it is
SELECT 1 FROM DUAL
for MaxDB as well.
For Oracle the high performing query will be
select 'X' from <your_small_table> where <primay_key_coulmn> = <some_value>
This is from a performance perspective.
I use this for Firebird
select 1 from RDB$RELATION_FIELDS rows 1
For MSSQL.
This helped me determine if linked servers were alive. Using an Open Query connection and a TRY CATCH to put the results of the error to something useful.
IF OBJECT_ID('TEMPDB..#TEST_CONNECTION') IS NOT NULL DROP TABLE #TEST_CONNECTION
IF OBJECT_ID('TEMPDB..#RESULTSERROR') IS NOT NULL DROP TABLE #RESULTSERROR
IF OBJECT_ID('TEMPDB..#RESULTSGOOD') IS NOT NULL DROP TABLE #RESULTSGOOD
DECLARE #LINKEDSERVER AS VARCHAR(25) SET #LINKEDSERVER = 'SERVER NAME GOES HERE'
DECLARE #SQL AS VARCHAR(MAX)
DECLARE #OPENQUERY AS VARCHAR(MAX)
--IF OBJECT_ID ('dbo.usp_GetErrorInfo', 'P' ) IS NOT NULL DROP PROCEDURE usp_GetErrorInfo;
--GO
---- Create procedure to retrieve error information.
--CREATE PROCEDURE dbo.usp_GetErrorInfo
--AS
--SELECT
-- ERROR_NUMBER() AS ErrorNumber
-- ,ERROR_SEVERITY() AS ErrorSeverity
-- ,ERROR_STATE() AS ErrorState
-- ,ERROR_PROCEDURE() AS ErrorProcedure
-- ,ERROR_LINE() AS ErrorLine
-- ,ERROR_MESSAGE() AS Message;
--GO
BEGIN TRY
SET #SQL='
SELECT 1
'''
--SELECT #SQL
SET #OPENQUERY = 'SELECT * INTO ##TEST_CONNECTION FROM OPENQUERY(['+ #LINKEDSERVER +'],''' + #SQL + ')'
--SELECT #OPENQUERY
EXEC(#OPENQUERY)
SELECT * INTO #TEST_CONNECTION FROM ##TEST_CONNECTION
DROP TABLE ##TEST_CONNECTION
--SELECT * FROM #TEST_CONNECTION
END TRY
BEGIN CATCH
-- Execute error retrieval routine.
IF OBJECT_ID('dbo.usp_GetErrorInfo') IS NOT NULL -- IT WILL ALWAYS HAVE SOMTHING...
BEGIN
CREATE TABLE #RESULTSERROR (
[ErrorNumber] INT
,[ErrorSeverity] INT
,[ErrorState] INT
,[ErrorProcedure] INT
,[ErrorLine] INT
,[Message] NVARCHAR(MAX)
)
INSERT INTO #RESULTSERROR
EXECUTE dbo.usp_GetErrorInfo
END
END CATCH
BEGIN
IF (Select ERRORNUMBER FROM #RESULTSERROR WHERE ERRORNUMBER = '1038') IS NOT NULL --'1038' FOR ME SHOWED A CONNECTION ATLEAST.
SELECT
'0' AS [ErrorNumber]
,'0'AS [ErrorSeverity]
,'0'AS [ErrorState]
,'0'AS [ErrorProcedure]
,'0'AS [ErrorLine]
, CONCAT('CONNECTION IS UP ON ', #LINKEDSERVER) AS [Message]
ELSE
SELECT * FROM #RESULTSERROR
END
learn.microsoft.com

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

C# SQL Top as parameter

Trying to parameterize the value of TOP in my sql statement.
SELECT TOP #topparam * from table1
command.Parameters.Add("#topparam",SqlDbType.VarChar, 10).Value = somevalue.ToString();
This doesn't seem to work. Anyone have any suggestions?
Just to clarify, I don't want to use stored procedures.
In SQL Server 2005 and above, you can do this:
SELECT TOP (#topparam) * from table1
You need to have at least SQL Server 2005. This code works fine in 2005/8 for example ...
DECLARE #iNum INT
SET #iNum = 10
SELECT TOP (#iNum) TableColumnID
FROM TableName
If you have SQL Server 2000, give this a try ...
CREATE PROCEDURE TopNRecords
#intTop INTEGER
AS
SET ROWCOUNT #intTop
SELECT * FROM SomeTable
SET ROWCOUNT 0
GO
You could write an inline query:
EXEC 'SELECT TOP ' + #topparam + ' * FROM ... '
Parse it as an int and that will prevent a SQL injection attack.