SQL multiple where clauses - sql

I have a procedure that has the options to take in Ids from three different columns I am concatenating all the where clauses together and then I EXEC the command.
Just wanted to see if there is a better way to do this?
IF ((ISNULL(#GuidelineIds, '')) <> '')
BEGIN
SET #whereClause = #whereClause + ' AND glinks.GuidelineId IN (SELECT val AS linkType FROM dbo.Split(''' + #GuidelineIds + ''','',''))'
END
IF ((ISNULL(#SubCategories, '')) <> '')
BEGIN
SET #whereClause = #whereClause + ' AND lt.LinkTypeID IN (SELECT val As subCategories FROM dbo.Split(''' + #SubCategories + ''', '',''))'
END
IF ((ISNULL(#LanguageIds, '')) <> '')
BEGIN
SET #whereClause = #whereClause + ' AND glinks.LanguageId IN (SELECT val As languages FROM dbo.Split(''' + #LanguageIds + ''', '',''))'
END

You can achieve it by this way
Select *
From ...
WHERE 1 = 1
AND ((ISNULL(#GuidelineIds, '')) = '' OR glinks.GuidelineId IN (SELECT val AS linkType FROM dbo.Split(''' + #GuidelineIds + ''','','')))
AND ((ISNULL(#SubCategories, '')) = '' OR lt.LinkTypeID IN (SELECT val As subCategories FROM dbo.Split(''' + #SubCategories + ''', '','')))
AND ((ISNULL(#LanguageIds, '')) = '' OR glinks.LanguageId IN (SELECT val As languages FROM dbo.Split(''' + #LanguageIds + ''', '','')))

Related

Msg 156, Level 15, State 1, Line 1 Incorrect syntax near the keyword 'SELECT'. Msg 102, Level 15, State 1, Line 1 Incorrect syntax near '.'

I try to run 2 dynamic SQL, but I have an error that the syntax is incorrect. When I make a select for every parameter that I declare, there is no problem. But when I try to execute the string I have these erroes. Any help?
Msg 156, Level 15, State 1, Line 1 Incorrect syntax near the keyword 'SELECT'. Msg 102, Level 15, State 1, Line 1 Incorrect syntax near '.'
--declare Variablen für die Prozedur
declare #DispoColumn nvarchar(max) = (select STRING_AGG(col.name, ', ') within group (order by col.column_id)
FROM sys.objects obj
JOIN sys.columns col on col.object_id = obj.object_id
JOIN sys.types typ ON col.user_type_id=typ.user_type_id
Where obj.name = #Tabelle and obj.schema_id = 5
GROUP BY obj.name);
declare #ID nvarchar(150) = (select MAX(CASE WHEN col.column_id = 1 THEN col.name ELSE NULL END)
FROM sys.objects obj
JOIN sys.columns col on col.object_id = obj.object_id
JOIN sys.types typ ON col.user_type_id=typ.user_type_id
Where obj.name = #Tabelle and obj.schema_id = 5
GROUP BY obj.name);
declare #EFREdispoUpdate nvarchar(max)
declare #ESFdispoUpdate nvarchar(max)
declare #ESFdispoInsert nvarchar(max)
declare #EFREdispoInsert nvarchar(max)
--Update der Tabellen
set #ESFdispoUpdate = 'UPDATE ESF.' + #Tabelle + ' SET GUELTIG_BIS = GETDATE() WHERE GUELTIG_BIS = ''9999-12-31'' AND ' + #ID + ' IN ( SELECT '
+ #ID + 'FROM ( SELECT ' +#DispoColumn + ' FROM ESF.' + #Tabelle + ' WHERE GUELTIG_BIS = ''9999-12-31''' + ' EXCEPT SELECT ' + #DispoColumn + ' SF.' + #Tabelle + ') as alt );'
+ ' UPDATE DISPO.T_TABELLEN SET ANZ_GEANDERT = (SELECT COUNT(*) FROM ESF.'+#Tabelle + ' WHERE GUELTIG_BIS = GETDATE())'
+ 'WHERE SCH_NAME = ''ESF'' AND TAB_NAME = ''' +#Tabelle + ''';';
set #EFREdispoUpdate = 'UPDATE EFRE.' + #Tabelle + ' SET GUELTIG_BIS = GETDATE() WHERE GUELTIG_BIS = ''9999-12-31'' AND ' + #ID + ' IN ( SELECT '
+ #ID + 'FROM ( SELECT ' +#DispoColumn + ' FROM EFRE.' + #Tabelle + ' WHERE GUELTIG_BIS = ''9999-12-31''' + ' EXCEPT SELECT ' + #DispoColumn + ' SF.' + #Tabelle + ') as alt );'
+ ' UPDATE DISPO.T_TABELLEN SET ANZ_GEANDERT = (SELECT COUNT(*) FROM EFRE.'+#Tabelle + ' WHERE GUELTIG_BIS = GETDATE())'
+ 'WHERE SCH_NAME = ''EFRE'' AND TAB_NAME = ''' +#Tabelle + ''';';
EXEC sp_executesql #ESFdispoUpdate;
EXEC sp_executesql #EFREdispoUpdate;
Your issue is because on the second line of your set statements, you forgot a space before FROM
Other minor changes
Added brackets to column names just in case column has special character like a space
Removed unnecessary GROUP BY clauses in subqueries
Changed second subquery from CASE WHEN to WHERE so it's more intuitive
DECLARE #Tabelle NVARCHAR(100) = 'YourTable'
declare #DispoColumn nvarchar(max) = (select STRING_AGG(QUOTENAME(col.name), ', ') within group (order by col.column_id)
FROM sys.objects obj
JOIN sys.columns col on col.object_id = obj.object_id
WHERE obj.name = #Tabelle AND obj.schema_id = 5
);
declare #ID nvarchar(150) = (SELECT QUOTENAME(col.name)
FROM sys.objects obj
JOIN sys.columns col on col.object_id = obj.object_id
Where obj.name = #Tabelle AND obj.schema_id = 5
AND col.column_id = 1
);
select #DispoColumn,#ID
declare #EFREdispoUpdate nvarchar(max)
,#ESFdispoUpdate nvarchar(max)
,#ESFdispoInsert nvarchar(max)
,#EFREdispoInsert nvarchar(max)
set #ESFdispoUpdate = 'UPDATE ESF.' + #Tabelle + ' SET GUELTIG_BIS = GETDATE() WHERE GUELTIG_BIS = ''9999-12-31'' AND ' + #ID + ' IN ( SELECT '
+ #ID + ' FROM ( SELECT ' +#DispoColumn + ' FROM ESF.' + #Tabelle + ' WHERE GUELTIG_BIS = ''9999-12-31''' + ' EXCEPT SELECT ' + #DispoColumn + ' SF.' + #Tabelle + ') as alt );'
+ ' UPDATE DISPO.T_TABELLEN SET ANZ_GEANDERT = (SELECT COUNT(*) FROM ESF.'+#Tabelle + ' WHERE GUELTIG_BIS = GETDATE())'
+ 'WHERE SCH_NAME = ''ESF'' AND TAB_NAME = ''' +#Tabelle + ''';';
set #EFREdispoUpdate = 'UPDATE EFRE.' + #Tabelle + ' SET GUELTIG_BIS = GETDATE() WHERE GUELTIG_BIS = ''9999-12-31'' AND ' + #ID + ' IN ( SELECT '
+ #ID + ' FROM ( SELECT ' +#DispoColumn + ' FROM EFRE.' + #Tabelle + ' WHERE GUELTIG_BIS = ''9999-12-31''' + ' EXCEPT SELECT ' + #DispoColumn + ' SF.' + #Tabelle + ') as alt );'
+ ' UPDATE DISPO.T_TABELLEN SET ANZ_GEANDERT = (SELECT COUNT(*) FROM EFRE.'+#Tabelle + ' WHERE GUELTIG_BIS = GETDATE())'
+ 'WHERE SCH_NAME = ''EFRE'' AND TAB_NAME = ''' +#Tabelle + ''';';
/*Use for debugging*/
SELECT #ESFdispoUpdate
SELECT #EFREdispoUpdate

Syntax Issue while Declaring select statement into a variable

If I run the select statement its working fine but if I defined into a variable then I am getting syntax error.
Declare #a varchar(2550)
SET #a='
SELECT 'ALTER DATABASE ' + CAST(DB_NAME() AS VARCHAR(50)) + ' MODIFY FILE ( NAME = ' +
QUOTENAME( df.name,'''') + ', NEWNAME = ''' +
QUOTENAME( DB_NAME()) +
+ CASE
WHEN df.type_desc = 'ROWS' AND df.file_id = 1 THEN '.mdf'' )'
WHEN df.type_desc = 'LOG' THEN '_log.ldf'' )'
WHEN df.type_desc = 'ROWS' AND df.file_id != 1 THEN '.ndf'' )'
END
FROM sys.database_files df'
select #a
Error:
Msg 102, Level 15, State 1, Line 38 Incorrect syntax near ' +
CAST(DB_NAME() AS VARCHAR(50)) + '.
It's a combination of typing errors and wrong use of SET and/or SELECT. If I understand you correctly, you may try to use the following statement:
DECLARE #a varchar(2550)
SELECT #a =
'ALTER DATABASE ' +
CAST(DB_NAME() AS VARCHAR(50)) +
' MODIFY FILE ( NAME = ' +
QUOTENAME( df.name,'''') + ', NEWNAME = ''' +
QUOTENAME( DB_NAME()) +
CASE
WHEN df.type_desc = 'ROWS' AND df.file_id = 1 THEN '.mdf'' )'
WHEN df.type_desc = 'LOG' THEN '_log.ldf'' )'
WHEN df.type_desc = 'ROWS' AND df.file_id != 1 THEN '.ndf'' )'
END
FROM sys.database_files df
SELECT #a
As an important note, when you use SELECT #local_variable and the SELECT statement returns more than one value, the variable is assigned the last value that is returned. So if you want to generate a complex statement for all database files, you need to concatenate the returned rows (using FOR XML PATH or STRING_AGG()). In this case, as #GordonLinoff commented, you may declare the #a variable as nvarchar(max):
DECLARE #a nvarchar(max) = N''
SELECT #a = (
SELECT
N'ALTER DATABASE ' +
CAST(DB_NAME() AS VARCHAR(50)) +
N' MODIFY FILE ( NAME = ' +
QUOTENAME( df.name,'''') +
N', NEWNAME = ''' +
QUOTENAME( DB_NAME()) +
CASE
WHEN df.type_desc = 'ROWS' AND df.file_id = 1 THEN N'.mdf'' )'
WHEN df.type_desc = 'LOG' THEN N'_log.ldf'' )'
WHEN df.type_desc = 'ROWS' AND df.file_id != 1 THEN N'.ndf'' )'
END +
N';'
FROM sys.database_files df
FOR XML PATH('')
)
SELECT #a
I think you're looking for something like this
declare #a nvarchar(max);
with file_cte as (
select
N'ALTER DATABASE ' + quotename(db_name()) +
N' MODIFY FILE ( NAME = ' + quotename( df.name,'''') +
N', NEWNAME = ''' + quotename(db_name()) +
case when df.type_desc = N'ROWS' AND df.file_id = 1 then N'.mdf'' )'
when df.type_desc = N'LOG' THEN N'_log.ldf'' )'
when df.type_desc = N'ROWS' AND df.file_id != 1 then N'.ndf'' )' end string
from sys.database_files df)
select #a=concat(string_agg(string, ';'), ';')
from file_cte;
select #a;

SQL Server trigger operation with out cursor

I have a scenario where in I have to generate SQL script after every DML operation. We have a trigger that runs after every Insert, Update, Delete.
Primarily it takes data from Inserted/Deleted tables and generates a SQL script for each row and performs an insert in to another table.
For example, If we insert
Take all inserted values
Open a cursor
For each inserted row, generate a SQL script that will be inserted in to another table for audit purpose
close cursor.
This trigger is taking almost 4-5 hours for 10,000 rows of 5 columns. Columns are int, date and varchar(100).
We are trying to replace the trigger. Need suggestions on same.
Set #syncScript = 'Insert Into table('
Declare insertCursor Cursor Local Forward_Only For
Select a, b, c From Inserted
Open insertCursor
Fetch Next From insertCursor Into #a, #b, #c
While (##Fetch_Status = 0)
Begin
Declare #valuesList varchar(max)
Set #columnList = ''
Set #paramsList = '['
Set #valuesList = ''
Select #columnList = #columnList + 'col6, ', #paramsList = #paramsList + '''' + COALESCE(dbo.ConvertFloatToVarchar(col6), 'NULL') + ''', ', #valuesList = #valuesList + '?, ' From Inserted I Where I.a= #a And I.b= #b And I.c= #c And 1 = 1
Select #columnList = #columnList + 'col5, ', #paramsList = #paramsList + '''' + COALESCE(Convert(varchar(max), col5), 'NULL') + ''', ', #valuesList = #valuesList + '?, ' From Inserted I Where I.a= #a And I.b= #b And I.c= #c And 1 = 1
Select #columnList = #columnList + 'col4, ', #paramsList = #paramsList + '''' + COALESCE(Convert(varchar(max), col4), 'NULL') + ''', ', #valuesList = #valuesList + '?, ' From Inserted I Where I.a= #a And I.b= #b And I.c= #c And 1 = 1
Select #columnList = #columnList + 'col3, ', #paramsList = #paramsList + '''' + COALESCE(Convert(varchar(max), col3), 'NULL') + ''', ', #valuesList = #valuesList + '?, ' From Inserted I Where I.a= #a And I.b= #b And I.c= #c And 1 = 1
Select #columnList = #columnList + 'col2, ', #paramsList = #paramsList + '''' + COALESCE(Convert(varchar(max), col2), 'NULL') + ''', ', #valuesList = #valuesList + '?, ' From Inserted I Where I.a= #a And I.b= #b And I.c= #c And 1 = 1
Select #columnList = #columnList + 'col1, ', #paramsList = #paramsList + '''' + COALESCE(Convert(varchar(max), col1), 'NULL') + ''', ', #valuesList = #valuesList + '?, ' From Inserted I Where I.TraitValueMemberId = #a And I.ValueSetId = #b And I.LanguageCulture = #c And 1 = 1
Set #columnList = SUBSTRING(#columnList, 1, Len(#columnList) - 1) + ') Values ('
Set #valuesList = SUBSTRING(#valuesList, 1, Len(#valuesList) - 1) + ')'
Set #paramsList = #paramsList + ']'
Set #bigScript = (COALESCE(#syncScript, '') + COALESCE(#columnList, '') + COALESCE(#valuesList, ''))
Insert Into Log (CreatedDate, [Message]) Select GetDate(), 'tablename INSERT syncScript = ' + #bigScript +'paramsList = ' + COALESCE(#paramsList, '')
Insert Into [dbo].[LogAudit] (GuidId, Query, Params, TableName, CreatedDate, Operation, UserId)
Values ('00000000-0000-0000-0000-000000000000', #bigScript, #paramsList, #table, GetDate(), #operation, #debugUser)
Fetch Next From insertCursor Into #a, #b, #c
End
Close insertCursor
Deallocate insertCursor
In case of update we join across inserted and deleted tables to generate update script like shown above.
I resolved the issue using SET Operation rather than Trigger
INSERT Into [dbo].[LogAudit] (GuidId, Query, Params, TableName, CreatedDate, Operation, UserId)
SELECT '00000000-0000-0000-0000-000000000000',
'INSERT INTO Table(col6, col5, col4, col3, col2, col1) VALUES (?, ?, ?, ?, ?, ?)',
'[' + '''' + COALESCE(dbo.ConvertFloatToVarchar(col6), 'NULL') + ''',' + '''' + COALESCE(Convert(varchar(max), col5), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col4), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col3), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col2), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col1), 'NULL') + ''', ' + ']', #table, GetDate(), #operation, #debugUser FROM Inserted
-- Insert into Log
Insert Into Log (CreatedDate, [Message]) Select GetDate(), 'MTDE_TraitValueMemberByLanguage_Sync INSERT
syncScript = INSERT Into [dbo].[LogAudit (GuidId, Query, Params, TableName, CreatedDate, Operation, UserId) VALUES VALUES (?, ?, ?, ?, ?, ?)' +
'paramsList = ' + '[' + '''' + COALESCE(dbo.ConvertFloatToVarchar(col6), 'NULL') + ''',' + '''' + COALESCE(Convert(varchar(max), col5), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col4), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col3), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col2), 'NULL') + ''', ' + '''' + COALESCE(Convert(varchar(max), col1), 'NULL') + ''', ' + ']' FROM Inserted

SQL join data row by level

I have table like this
level|value
1 |ABC
1 |XYZ
1 |QWER
2 |1234
2 |7360
3 |zxcv
3 |0001
How can I join each value on level 1 to all level below? Like:
ABC-1234-zxcv
ABC-1234-0001
ABC-7360-zxcv
...
It the number of levels is not fixed:
Declare #select varchar(max) = 'SELECT ',
#from varchar(max) = 'FROM ',
#where varchar(max) = 'WHERE ',
#query varchar(max)= '';
SELECT #select = #select + 't' + cast([level] as varchar(max)) + '.[value]+''-''+',
#from = #from + 'yourTable t' + cast([level] as varchar(max)) + ',',
#where = #where + 't' + cast([level] as varchar(max)) + '.[level] = ' + cast([level] as varchar(max)) + ' AND '
FROM yourTable
GROUP BY [level]
Set #query = SUBSTRING(#select, 1, len(#select) - 5) + ' ' +
SUBSTRING(#from, 1, len(#from) - 1) + ' ' +
SUBSTRING(#where, 1, len(#where) - 4) + ' ORDER BY 1'
EXEC(#query)
If you have always 3 levels, you can do it like this:
select
d1.value + '-' + d2.value + '-' + d3.value
from
data d1
cross join data d2
cross join data d3
where
d1.level = 1 and
d2.level = 2 and
d3.level = 3
order by
1
If the number of levels isn’t fixed, then you'll probably have to use a recursive CTE

How to copy, replace, and insert across all rows in the database

I'll do my best to explain:
Copy all rows that exist in current database
Mass replace a specific string value in every row that contains a specific field
Insert the copied rows
Not sure what approach to take other than hammering out sql scripts.
Thanks!
Is this as simple as creating an Data Flow Source, selecting all the rows, then passing them to a Derived Column transformation, which would be along the lines of:
REPLACE( [ColumnName], "SpecificValue", "ReplacementValue" )
and then insert these rows into your destination table using the relevant Data Flow Destination.
I may be misunderstanding or simplifying step 2...
Assuming you have a table called "table2" and that table consists of the columns facilabbr, unitname, and sortnum... You can select all rows into a temporary table (# signifies a temporary table) changing the "unitname" column to something else...You'll be left with the new values in the temporary table. You can then replace the values in your initial table if you want.
INSERT INTO #temptable1
SELECT facilabbr,
'myNewUnitName' as unitname,
sortnum
FROM table2
DELETE FROM table2
INSERT INTO table2
SELECT facilabbr,
unitname,
sortnum
FROM #temptable1
--THIS QUERY IS ONLY EQUIPPED TO HANDLE:
--SIMPLE NUMERICS SUCH AS FLOATS, INTS, ETC
--SIMPLE STRING DATA TYPES LIMITED TO: VARCHARS, CHARS, NCHARS AND NVARCHARS
--DATES AND DATETIMES
Create Procedure SQLCloner
#TableName as VarChar(max), -- Table that holds data to clone.
#NewTableName as VarChar(max) = '', -- Table to Insert into. If same as Tablename leave blank or write ''.
#VarCharFind as VarChar(max) = '', -- Value to find (In order to replace). If you aren't replacing leave blank or write ''.
#VarCharReplace as VarChar(max) = '', -- Value to replace. If you aren't replacing leave blank or write ''.
#OptionalParam As VarChar(Max) = '' -- Your WHERE clause. If you have none leave blank or write ''.
AS
Declare #index as int = 1
Declare #rowcount As Int = 0
Declare #execFunction As VarChar(max) = ''
Declare #InsertTableRowName As VarChar(max) = ''
Declare #TempFilterType As VarChar(Max) = ''
--Create RowCount of Table
Select #ROWCOUNT = Count(*)
From (
Select Column_Name
From INFORMATION_SCHEMA.COLUMNS
Where Table_Name = '' + #TableName + ''
) As TheCount
--Use While Loop to create Table Columns
While #index <= #rowcount
Begin
--Determines the Variable type to change the exec function accordingly
Select #TempFilterType = TypeTable.DATA_TYPE
From (
Select Data_Type,
ROW_NUMBER() OVER (Order By Ordinal_Position) as RowNum
From INFORMATION_SCHEMA.COLUMNS
Where Table_Name = #TableName
) As TypeTable
Where TypeTable.RowNum = #index
--Prepares #InsertTableRowName With the first part of the string
Set #InsertTableRowName = Case
When #TempFilterType IN('varchar', 'nvarchar','char', 'nchar')
Then #InsertTableRowName + ''''''''' + '
When #TempFilterType IN('datetime', 'date')
Then #InsertTableRowName + ''''''''' + Convert(varchar(Max), '
Else
#InsertTableRowName + 'Convert(varchar(Max), '
End
--Determines the Name of the Column
Select #InsertTableRowName = #InsertTableRowName +
Case
When #TempFilterType IN('varchar', 'nvarchar','char', 'nchar')
Then 'ISNULL(' + 'Replace(' + Column_Name + ','''''''','''''''''''')' + ','''')'
When #TempFilterType IN('datetime', 'date')
Then 'ISNULL(' + 'Replace(' + Column_Name + ','''''''','''''''''''')' + ',''12/31/9999'')'
Else
'ISNULL(' + 'Replace(' + Column_Name + ','''''''','''''''''''')' + ',0)'
End
From (
Select Column_Name,
ROW_NUMBER() OVER (Order By Ordinal_Position) As RowNum
From INFORMATION_SCHEMA.COLUMNS
Where Table_Name = #TableName
) As TheRow
Where RowNum = #index
--Finishes Closes each column insert (in every instance)
Set #InsertTableRowName = Case
When #TempFilterType IN('varchar', 'nvarchar','char', 'nchar')
Then #InsertTableRowName + ' + '''''''''
When #TempFilterType IN('datetime', 'date')
Then #InsertTableRowName + ') + '''''''''
Else
#InsertTableRowName + ') '
End
--Links each Row together with commas and plus signs until the very end.
If #index < #rowcount
Begin
Set #InsertTableRowName = Case
When #TempFilterType IN('varchar', 'nvarchar','char', 'nchar')
Then #InsertTableRowName + ' + ' + ''',''' + ' + '
When #TempFilterType IN('datetime', 'date')
Then #InsertTableRowName + ' + '','' + '
Else
#InsertTableRowName + ' + '','' + '
End
End
Set #index = #index + 1
End
--Puts the Query together (without any of the Parameters yet).
--First, determine if a new table should be used instead.
If #NewTableName = ''
Begin
Set #NewTableName = #TableName
End
--Next, Build the Query, and do it accordingly with if there is a Find/Replace asked for.
Set #execFunction = 'Select '
If #VarCharFind <> ''
Begin
Set #execFunction = #execFunction + 'Replace('
End
Set #execFunction = #execFunction + '''insert into ' + #NewTableName + ' Values('' + ' + #InsertTableRowName + ' + '')'' '
If #VarCharFind <> ''
Begin
Set #execFunction = #execFunction + ', ''' + #VarCharFind + ''', ''' + #VarCharReplace + ''') '
End
Set #execFunction = #execFunction + 'From ' + #TableName
--Adds in the optional Parameters
If #OptionalParam <> ''
Begin
Set #execFunction = #execFunction + ' ' + #OptionalParam
End
Set #execFunction = #execFunction + CHAR(13)+CHAR(10)
--Executes the function and pulls an entire set of queries to copy into the new Database
Print #execFunction
Exec(#execFunction)
GO