SQL - concatenation and iteration - sql-server

Wanted to know if there is a way of iterating and concatenating a string in SQL to a new column every cycle in a while loop.
set nocount on
declare #rowcount INT,
#BL_A VARCHAR(MAX)
set #rowcount =2
while #rowcount <=12
begin
set #BL_A = '[DB1].[dbo].[Table1].[Col_'+CAST(#rowcount as varchar(MAX))+']'
print #BL_A
update [DB1].[dbo].[Table1]
set #BL_A = [DB2].[dbo].[Table2].[Y_Value]
from [DB2].[dbo].[Table2]
where [DB1].[dbo].[Table1].[X_Value] = [DB2].[dbo].[Table2].[X_Value];
set #rowcount= #rowcount+1
end
print 'End of Script'
The query runs without errors and prints off this, but doesn't update the columns
[DB1].[dbo].[Table1].[Col_2]
[DB1].[dbo].[Table1].[Col_3]
....
[DB1].[dbo].[Table1].[Col_12]
End of Script

Please create the dynamic query to update the table, try like below:
exec ('update [DB1].[dbo].[Table1]
set '+#BL_A+' = [DB2].[dbo].[Table2].[Y_Value]
from [DB2].[dbo].[Table2]
where [DB1].[dbo].[Table1].[X_Value] = [DB2].[dbo].[Table2].[X_Value];')
HTH!

Related

SQL Server Conditional Select Into Issue [duplicate]

I have a T-Sql script where part of this script checks to see if a certain column exists in the a table. If so, I want it to execute a routine... if not, I want it to bypass this routine. My code looks like this:
IF COL_LENGTH('Database_Name.dbo.Table_Name', 'Column_Name1') IS NOT NULL
BEGIN
UPDATE Table_Name
SET Column_Name2 = (SELECT Column_Name3 FROM Table_Name2
WHERE Column_Name4 = 'Some Value')
WHERE Column_Name5 IS NULL;
UPDATE Table_Name
SET Column_Name6 = Column_Name1
WHERE Column_Name6 IS NULL;
END
My problem is that even when COL_LENGTH of Column_Name1 is null (meaning it does not exist) I am still getting an error telling me "Invalid column name 'Column_Name1'" from the 2nd UPDATE statement in the IF statement. For some reason this IF condition is still being evaluated even when the condition is FALSE and I don't know why.
SQL Server parses the statement and validates it, ignoring any if conditionals. This is why the following also fails:
IF 1 = 1
BEGIN
CREATE TABLE #foo(id INT);
END
ELSE
BEGIN
CREATE TABLE #foo(id INT);
END
Whether you hit Execute or just Parse, this results in:
Msg 2714, Level 16, State 1
There is already an object named '#foo' in the database.
SQL Server doesn't know or care which branch of a conditional will be entered; it validates all of the statements in a batch anyway. You can do things like (due to deferred name resolution):
IF <something>
BEGIN
SELECT foo FROM dbo.Table_That_Does_Not_Exist;
END
But you can't do:
IF <something>
BEGIN
SELECT column_that_does_not_exist FROM dbo.Table_That_Does;
END
The workaround, typically, is to use dynamic SQL:
IF <something>
BEGIN
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'SELECT column_that_does_not_exist FROM dbo.Table_That_Does;';
EXEC sp_executesql #sql;
END
Make your statement a string. And if column exists, execute it
IF COL_LENGTH('Database_Name.dbo.Table_Name', 'Column_Name1') IS NOT NULL
BEGIN
DECLARE #sql VARCHAR(MAX)
SET #sql = 'UPDATE Table_Name
SET Column_Name2 = (SELECT Column_Name3 FROM Table_Name2
WHERE Column_Name4 = ''Some Value'')
WHERE Column_Name5 IS NULL;
UPDATE Table_Name
SET Column_Name6 = Column_Name1
WHERE Column_Name6 IS NULL;'
EXEC(#sql)
END

using script in a variable

Can you declare a variable, set it as a script definition and then execute it repeatedly throughout your script? I understand how to set a variable to the result of a script, but I want to re-use the definition itself. This is because I want to occasionally get the count from a script and sometimes the top result throughout the rest of my script and I want to make it so the script is easily customized by only needing to change the script once at the beginning.
An example:
declare #RepeatScript nvarchar(200)
declare #count int
declare #topresult int
set #RepeatScript = ' from Table1 where something = 1 and something else > getdate()-5'
set #count = select count(ID) & #RepeatScript
set #topresult = select top 1 (ID) & #RepeatScript
This very simple case would be simple to fix, but if I wanted to reference the same set of information multiple times without having to create and drop a temp_table over and over, this would be very helpful. I do this kind of thing in MS Access all the time, but I can't seem to figure out how to do it in SSMS.
You don't need to repeatedly run these queries. You don't even need to run more than 1 query to capture this information. This will capture both pieces of data in a single query. You can then reference that information anywhere else within the current batch. This meets your criteria of simply changing the script at the beginning.
declare #count int
, #topresult int
select #count = count(ID)
, #topresult = MAX(ID) --MAX would the same thing as top 1 order by ID desc
from Table1
where something = 1
declare #RepeatScript nvarchar(200)
declare #count varchar(200)
declare #topresult varchar(200)
set #RepeatScript = ' from Table1 where something = 1 and something else > getdate()-5'
set #count = 'select count(ID) '+#RepeatScript+''
set #topresult = 'select top 1 (ID)'+#RepeatScript+''
print (#count)
print (#topresult)
Something like that? but instead of using print you would be using exec to run the select statement. Does that help?

T-Sql appears to be evaluating "If" statement even when the condition is not true

I have a T-Sql script where part of this script checks to see if a certain column exists in the a table. If so, I want it to execute a routine... if not, I want it to bypass this routine. My code looks like this:
IF COL_LENGTH('Database_Name.dbo.Table_Name', 'Column_Name1') IS NOT NULL
BEGIN
UPDATE Table_Name
SET Column_Name2 = (SELECT Column_Name3 FROM Table_Name2
WHERE Column_Name4 = 'Some Value')
WHERE Column_Name5 IS NULL;
UPDATE Table_Name
SET Column_Name6 = Column_Name1
WHERE Column_Name6 IS NULL;
END
My problem is that even when COL_LENGTH of Column_Name1 is null (meaning it does not exist) I am still getting an error telling me "Invalid column name 'Column_Name1'" from the 2nd UPDATE statement in the IF statement. For some reason this IF condition is still being evaluated even when the condition is FALSE and I don't know why.
SQL Server parses the statement and validates it, ignoring any if conditionals. This is why the following also fails:
IF 1 = 1
BEGIN
CREATE TABLE #foo(id INT);
END
ELSE
BEGIN
CREATE TABLE #foo(id INT);
END
Whether you hit Execute or just Parse, this results in:
Msg 2714, Level 16, State 1
There is already an object named '#foo' in the database.
SQL Server doesn't know or care which branch of a conditional will be entered; it validates all of the statements in a batch anyway. You can do things like (due to deferred name resolution):
IF <something>
BEGIN
SELECT foo FROM dbo.Table_That_Does_Not_Exist;
END
But you can't do:
IF <something>
BEGIN
SELECT column_that_does_not_exist FROM dbo.Table_That_Does;
END
The workaround, typically, is to use dynamic SQL:
IF <something>
BEGIN
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'SELECT column_that_does_not_exist FROM dbo.Table_That_Does;';
EXEC sp_executesql #sql;
END
Make your statement a string. And if column exists, execute it
IF COL_LENGTH('Database_Name.dbo.Table_Name', 'Column_Name1') IS NOT NULL
BEGIN
DECLARE #sql VARCHAR(MAX)
SET #sql = 'UPDATE Table_Name
SET Column_Name2 = (SELECT Column_Name3 FROM Table_Name2
WHERE Column_Name4 = ''Some Value'')
WHERE Column_Name5 IS NULL;
UPDATE Table_Name
SET Column_Name6 = Column_Name1
WHERE Column_Name6 IS NULL;'
EXEC(#sql)
END

MSSQL nvarchar IF PROCEDURE exec with nvarchar input

I want know how to release IF with update and how to exec procedure with nvarchar input.
There are table Dictionary with 2 values ('Orig','Translated')
I need procedure that adds or replace "Trasnslated' depending on input. There must be 2 inputs, no more and no less. For example
CREATE PROCEDURE Translate_Orig (#Orig nvarchar(32),#Translated nvarchar(32))
AS
BEGIN
UPDATE Dictionary
IF EXISTS (SELECT * FROM Dictionary WHERE Dictionary.Orig=#Orig)
SET Dictionary.Translated=#Translated
ELSE INSERT INTO Dictionary VALUES (#Orig, #Translated);
END
GO
SET #Orig = N'Orig'
SET #Translated = N'traslated'
EXEC Translate_Orig (#Orig,#Translated);
CREATE PROCEDURE Translate_Orig (#Orig nvarchar(32),#Translated nvarchar(32))
AS
BEGIN
IF EXISTS (SELECT * FROM Dictionary WHERE Dictionary.Orig=#Orig)
BEGIN
UPDATE Dictionary
SET Dictionary.Translated=#Translated
END
ELSE INSERT INTO Dictionary VALUES (#Orig, #Translated);
END
GO
SET #Orig = N'Orig'
SET #Translated = N'traslated'
EXEC Translate_Orig (#Orig,#Translated);
Make sure you are just running the CREATE PROCEDURE through GO as a statement.
There EXEC that works fine. No brackets.
And "SET Dictionary.Translated=#Translated WHERE Dictionary.Orig=#Orig"
CREATE PROCEDURE Translate_Orig (#Orig nvarchar(32),#Translated nvarchar(32))
AS
BEGIN
IF EXISTS (SELECT * FROM Dictionary WHERE Dictionary.Orig=#Orig)
BEGIN
UPDATE Dictionary
SET Dictionary.Translated=#Translated WHERE Dictionary.Orig=#Orig
END
ELSE INSERT INTO Dictionary VALUES (#Orig, #Translated);
END
GO
DECLARE #Orig nvarchar(32);
DECLARE #Translated nvarchar(32);
SET #Orig = N'Name'
SET #Translated = N'Name_Translated'
EXEC Translate_Orig #Orig,#Translated;

Efficiently return a value from a stored procedure

I have query which returns single value (i.e) count. I'm exceuting it using the stored procedure in the following way and using execute reader with dataset to get single value
CREATE PROCEDURE GetCnt
#EmpNo char(4)
AS
BEGIN
SET NOCOUNT ON;
Declare #Cnt int
SELECT #Cnt = count(*)
FROM employees
WHERE EMPLNO = #EmpNo
AND test = 'p'
BEGIN
SELECT #Cnt
END
END
is this effcient way
or Do I need to use the execute.scalar() and return value directly from the query instead of assigning to #cnt
can any one advise me
All ExecuteScalar does is get the first field from the first record.
Can't you just SELECT the count directly?
BEGIN
SET NOCOUNT ON
SELECT Count(*) FROM employees WHERE EMPLNO = #EmpNo AND test='p'
END
You do not need to create the variable. You just need the following:
CREATE PROCEDURE GetCnt
#EmpNo char(4)
AS
BEGIN
SET NOCOUNT ON;
SELECT count(1)
FROM employees
WHERE EMPLNO = #EmpNo
AND test = 'p'
END
Since this is only one value being returned from the stored procedure, you will likely want to use ExecuteScalar()

Resources