Modify columns using stored procedure in SQL Server - sql

I wish to modify strings in several columns (for example all columns containing the 'sound' string), for example replacing ',' by '.'. Further to this post, I understand I have to use dynamic SQL. I created the following procedure:
USE [myDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[RemoveStringInColumn] (#colName varchar(50), #tableName varchar(50), #to_remove varchar(50), #to_add varchar(50))
AS
DECLARE #sql nvarchar(4000)
SET #sql = 'UPDATE ' + #tableName + ' SET ' + #colName + ' = REPLACE(' + #colName + ',' + #to_remove + ','+ #to_add + ');'
PRINT #sql
EXEC sp_executesql #sql
Which is called by:
EXEC dbo.RemoveStringInColumn 'COL_1', 'TABLE_1', ',', '.'
1) The problem is the #sql command does not contain the little hyphen arond the comma and the dot. How can I solve this?
2) In this post they use a SELECT command to fetch all column names. So far, I managed to fetch column names containing 'sound'.
select COLUMN_NAME AS my_cols
from INFORMATION_SCHEMA.COLUMNS
where table_name = 'TABLE_1' AND COLUMN_NAME LIKE '%sound%'
How can I put column names into a list and use a for loop to go through them calling the RemoveStringInColumn procedure?
Thanks

Just double the single quotes around #to_remove and #to_add
DECLARE #sql NVARCHAR(4000)
SET #sql = 'UPDATE ' + Quotename(#tableName) + ' SET ' + Quotename(#colName)
+ ' = REPLACE(' + Quotename(#colName) + ',''' + #to_remove + ''','''
+ #to_add + ''');'
PRINT #sql
EXEC Sp_executesql
#sql
Update : To do the replace for more than one column
DECLARE #sql NVARCHAR(4000),
#col_list VARCHAR(8000)= ''
SET #col_list = (SELECT ',' + Quotename(COLUMN_NAME) + ' = REPLACE('
+ Quotename(COLUMN_NAME) + ',''' + #to_remove
+ ''',''' + #to_add + ''')'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'TABLE_1'
AND COLUMN_NAME LIKE '%sound%'
FOR xml path(''))
SET #col_list = Stuff(#col_list, 1, 1, '')
SELECT #col_list
SET #sql = 'UPDATE ' + Quotename(#tableName) + ' SET '
+ #col_list
PRINT #sql
EXEC Sp_executesql
#sql

Related

Stored procedure does not return value in column

I have this problem. I have this query in which I used to model a stored procedure and I want to get the value in the column clr_bal_amt. I want it to return as a string from the database column.
However it does not return it. The query executes, but it does not get the value in that column.
The stored procedure looks like this
CREATE PROCEDURE FindBranchVaultBalance
#sol_id varchar(50),
#acct_crncy_code varchar(50)
AS
DECLARE #query nvarchar(max) = N'
select foracid, acct_crncy_code, clr_bal_amt
from dummy_table
where bacid = ''1010000001'' and sol_id = ' + QUOTENAME(#sol_id, '''') + N' and
acct_crncy_code = ' + QUOTENAME(#acct_crncy_code, '''') + N' and
del_flg = ''N'' and acct_cls_flg = ''N''
';
DECLARE #sql nvarchar(max) = N'
SELECT *
FROM OPENQUERY (LINKEDSERVER, N' + QUOTENAME(#query, '''') + N' )
';
EXEC sp_executesql #sql;
GO
I need some form of clarification. Why did this not return that value in that clr_bal_amt column?
Edited
The SQL is looking like this now
ALTER PROCEDURE [dbo].[FindBranchVaultBalance]
#sol_id varchar(50),
#acct_crncy_code varchar(50)
AS
DECLARE #query nvarchar(max) = N'
select foracid, acct_crncy_code, clr_bal_amt
from dummy_table
where bacid = ''1010000001'' and sol_id = ' + QUOTENAME(#sol_id, '''') + N' and
acct_crncy_code = ' + QUOTENAME(#acct_crncy_code, '''') + N' and
del_flg = ''N'' and acct_cls_flg = ''N''
';
DECLARE #sql nvarchar(max) = N'
SELECT *
FROM OPENQUERY (LINKEDSERVER, N' + REPLACE(#query, '''','''''') + N' )
';
EXEC sp_executesql #sql;
Edits2
ALTER PROCEDURE [dbo].[FindAFINACLEBranchVaultBalance]
#sol_id varchar(50),
#acct_crncy_code varchar(50)
AS
DECLARE #query nvarchar(max) = N'
select foracid, acct_crncy_code, clr_bal_amt
from dummy_table
where bacid = ''1010000001'' and sol_id = ' + QUOTENAME(#sol_id, '''') + N' and
acct_crncy_code = ' + QUOTENAME(#acct_crncy_code, '''') + N' and
del_flg = ''N'' and acct_cls_flg = ''N''
';
DECLARE #sql nvarchar(max) = N'
SELECT *
FROM OPENQUERY (LINKEDSERVER, N' + '... N''' + REPLACE(#query, '''','''''') + N''' ...'+ N' )
';
EXEC sp_executesql #sql;
Is there something I am missing?
As I mentioned QUOTENAME accepts a sysname as a parameter (a synonym of nvarchar(128) NOT NULL), and your variable #query is defined as an nvarchar(MAX). As such if it's 129 or more characters long it'll be truncated; your value is clearly more than 128 characters.
Just use REPLACE:
N'... N''' + REPLACE(#query, '''','''''') + N''' ...'
As a bit of shameless self promotion, I explain this scenario more in-depth here.
To add emphasis on the OP's attempt to implement this, your attempt is not the same:
N'... N' + REPLACE(#query, '''','''''') + N' ...'
Notice the lack of trailing and leading single quotes ('). The single quotes are needed. REPLACE replaces characters, it doesn't delimit identify them like QUOTENAME does.

SQL Server: how to replace the line breaks in the text fields?

I have the following SQL
SELECT COLUMN_NAME
FROM Information_Schema.Columns
WHERE TABLE_NAME = 'TABLE'
AND DATA_TYPE = 'varchar'
ORDER BY COLUMN_NAME
It returns:
COLUMN_NAME
-------------------
CiudadConductor
CiudadPropietario
CodBaseLegal
DireccConductor
DireccPropietario
PTActa
PTClase
PTCodCategoriaClase
PTCodCIP
PTCodiConductor
With this SQL I need to identify the varchar columns that exist, but I want to do a data update.
I know that this SQL replaces but how do I make the two SQL statements work together.
REPLACE(ColumnName, CHAR(13),'')
I want to remove the line breaks in all varchar columns
This should work (untested), however, the PRINT will guide you if it's perhaps a little "off":
DECLARE #SQL nvarchar(MAX),
#Table sysname = N'T700InfracTrans';
SET #SQL = N'UPDATE ' + QUOTENAME(#Table) + NCHAR(13) + NCHAR(10) +
N'SET ' + STUFF((SELECT N',' + NCHAR(13) + NCHAR(10) +
N' ' + QUOTENAME(COLUMN_NAME) + N' = REPLACE(REPLACE(' + QUOTENAME(COLUMN_NAME) + N',CHAR(13),''''),CHAR(10),'''')'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #Table
AND DATA_TYPE = N'varchar'
ORDER BY COLUMN_NAME
FOR XML PATH(''),TYPE).value('.','nvarchar(MAX)'),1,7,N'') + N';';
PRINT #SQL; --Your debugging best friend.
--EXEC sp_executesql #SQL; --Uncomment to execute
Try this
DECLARE #SqlTab TABLE(ID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, SQL NVARCHAR(MAX) NOT NULL)
DECLARE #TableName sysname = 'TableName'
INSERT INTO #SqlTab(Sql)
SELECT
SQL = 'UPDATE ' + QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) + ' SET ' + QUOTENAME(COLUMN_NAME) + ' = REPLACE(REPLACE(' + COLUMN_NAME + ', CHAR(13), ''''), CHAR(10), '''') '
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = #TableName --<-- Remove if you want to strip out CRLF in All Tables
AND DATA_TYPE IN('VARCHAR')
ORDER BY
TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME
DECLARE #ID INT = -1, #Sql NVARCHAR(MAX)
WHILE(1 = 1)
BEGIN
SELECT
#ID = ID
,#Sql = Sql
FROM
#SqlTab
WHERE
ID > #ID
IF ##ROWCOUNT = 0 BREAK
--PRINT #Sql
EXEC SP_ExecuteSql #Sql
END

How to pass column name as variable in dynamic query in SQL Server?

I have the below query, which gives the count of distinct values for each column. But I need to add a where clause condition in the query such as column1 = 'abc'. I am using this generic query so that I can use the same query with other tables also by passing the table name.
DECLARE #query VARCHAR(MAX)
SELECT #query =
'SELECT ' + SUBSTRING((SELECT ',' +'COUNT(DISTINCT(' + column_name + ')) AS ' + column_name + ' '
FROM information_schema.columns
WHERE table_name = 'table_name'
FOR XML PAT('')), 2, 100000) + 'FROM table_name'
--PRINT(#query)
EXECUTE(#query)
I tried passing it as below.
WHERE
table_name = 'table_name'
AND column1 = 'abc' -- compilation error, obviously
WHERE
table_name = 'table_name'
AND 'column1' = 'abc' -- not working, because it will compare the string values column1 and abc. and both are not equal
Then I just gave a try with the below query, but this is also not working, it's generating the wrong query when I try to print.
DECLARE #SQL NVARCHAR(MAX), #tname NVARCHAR(100),
#cname NVARCHAR(100), #acc_num NVARCHAR(50), #dp_code NVARCHAR(100)
SET #cname = 'column_name';
SET #acc_num = 'xyz';
SET #tname = 'table_name';
DECLARE #query VARCHAR(MAX);
SET #SQL = ''
;with cols as (
select Table_Schema, Table_Name, Column_Name, Row_Number() over(partition by Table_Schema, Table_Name
order by ORDINAL_POSITION) as RowNum
from INFORMATION_SCHEMA.COLUMNS
)
SELECT #query =
'SELECT ' + SUBSTRING((SELECT ',' +'COUNT(DISTINCT(' + QUOTENAME(column_name, '') + ')) As ' + QUOTENAME(column_name, '')+ ' '
+ ' WHERE ' + 'column_name' + ' = ''' + #acc_num + ''''
FROM cols
WHERE
table_name = #tname
for xml path('')),2,200000) + 'FROM' #tname
--for xml path('');
PRINT #query
--execute (#query)
This should be what you are after. There's a few comments in the SQL you need to pay attention to:
DECLARE #SQL nvarchar(max),
#tname sysname, --note the datatype change
#cname sysname, --note the datatype change
#acc_num nvarchar(50),
#dp_code nvarchar(100); --This is never used in your sample query
SET #cname = 'column_name';
SET #acc_num = 'xyz';
SET #tname = 'table_name';
SET #SQL = N'SELECT ' + NCHAR(13) + NCHAR(10) +
STUFF((SELECT N',' + NCHAR(13) + NCHAR(10) +
N' ' + N'COUNT DISTINCT(' + QUOTENAME(C.Column_Name) + N') AS ' + QUOTENAME(C.Column_Name)
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.Table_Name = #tname
ORDER BY C.ORDINAL_POSITION
FOR XML PATH(N'')),1,10,N'') + NCHAR(13) + NCHAR(10) +
N'FROM ' + QUOTENAME(#tname) + NCHAR(13) + NCHAR(10) +
N'WHERE ' + QUOTENAME(#cname) + N' = #Acc_Num;'
PRINT #SQL; --YOur debugging best friend
EXEC sp_executesql #SQL, N'#Acc_Num varchar(100)',#Acc_Num = #acc_num;
This parametrised the query instead, using sp_executesql, and nicely formats it for your PRINT statement.
If you don't understand then please do ask.
If you want a WHERE clause in the dynamic query, then you have to put it after the FROM clause in the dynamic query.
...
for xml path('')),2,200000) + ' FROM '+ #tname
+ ' WHERE ' + 'column_name' + ' = ''' + #acc_num + ''''

stored procedure to remove quotes

I am trying to write a stored procedure that will removed leading and trailing quotes from an arbitrary table and column. I keep getting an error saying that the table name isn't declared.
Here is the SP
create table [dbo].[test] (id nvarchar(20))
insert into dbo.test values ('"07617966004766"')
go
CREATE PROCEDURE sp_stripDoubleQuotes
#tableName sysname,
#columnName sysname
AS
BEGIN
SET NOCOUNT ON;
UPDATE #tableName
SET #columnName = SUBSTRING(#columnName, 2, LEN(#columnName))
WHERE LEFT(#columnName, 1) = '"'
UPDATE #tableName
SET #columnName = SUBSTRING(#columnName, 1, LEN(#columnName)-1)
WHERE RIGHT(#columnName, 1) = '"'
END
GO
exec [dbo].[sp_stripDoubleQuotes] N'[dbo].[test]', N'[id]'
select * from test
Here is a link to a fiddle:
link to fiddle
CREATE PROCEDURE sp_stripDoubleQuotes
#tableName sysname,
#columnName sysname,
#SQL varchar(MAX)
AS
BEGIN
SET NOCOUNT ON;
SET #SQL =
'UPDATE ' + '[' + #tableName +']' +
'SET' + '[' + #columnName +']' +'= SUBSTRING(' +'[' + #columnName +']' +', 2, LEN(' +'[' + #columnName +']' +'))
WHERE LEFT(' + '[' + #columnName +']' +', 1) = '+'''"'''
--PRINT(#SQL)
EXEC (#SQL)
SET #SQL =
'UPDATE ' + '[' + #tableName +']' +
'SET' + '[' + #columnName +']' +'= SUBSTRING(' + '[' + #columnName +']' +', 1, LEN(' + '[' + #columnName + ']' +')-1)
WHERE RIGHT(' + '[' + #columnName +']' +', 1) = '+'''"'''
--PRINT(#SQL)
EXEC (#SQL)
END
GO
exec [dbo].[sp_stripDoubleQuotes] N'test', N'id' -- exec [dbo].[sp_stripDoubleQuotes] N'[dbo].[test]', N'[id]'
Updated 2nd: I added [] to wrap table and column incase your table and column name have whitespace in them. Thanks #Sean Lange and #Richard
Updated 3rd: As #[benjamin moskovits] (xD) mentioned, if you hard coded brackets, the correct execute command is exec [dbo].[sp_stripDoubleQuotes] N'test', N'id'. Try to add or remove brackets and print to see whether the syntax is correct before executing it.
CREATE PROCEDURE sp_stripDoubleQuotes
#tableName sysname,
#columnName sysname
AS
BEGIN
SET NOCOUNT ON;
declare #QuerytoExecute varchar(1000)
set #QuerytoExecute="UPDATE "+#tableName+"
SET "+#columnName+" = SUBSTRING("+#columnName+", 2, LEN("+#columnName+"))
WHERE LEFT("+#columnName+", 1) = '""'";
exec (#QuerytoExecute);
set #QuerytoExecute="
UPDATE "+#tableName+"
SET "+#columnName+" = SUBSTRING("+#columnName+", 1, LEN("+#columnName+")-1)
WHERE RIGHT("+#columnName+", 1) = '""'";
exec (#QuerytoExecute);
END
GO

Dynamic SQL, Empty Variable, Formatting Issue?

I am using dynamic SQL to build out some statements. Here is a truncated example of a stored proc UpdateFOO. When I debug this stored procedure, the problem is the #SQL variable I am declaring always stay empty! It is supposed to fill with the query. I suspect it has something to do with how I am formatting this, but I cant spot if its a bad formatting error.
CREATE PROC [dbo].[UpdateFOO]
#TEST1 uniqueidentifier,
#TEST2 nvarchar(40),
#TEST3 nvarchar(50),
#TEST4 char(1),
#TEST5 nvarchar(20),
#TEST6 nvarchar(40),
#LINKED_SERVER_NAME nvarchar(max),
#DATABASE_NAME nvarchar(max)
AS
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRAN
DECLARE #SQL nvarchar(max)
SELECT #SQL = 'UPDATE [' + #LINKED_SERVER_NAME + '].[' + #DATABASE_NAME + '].[dbo].[SOME_TABLE]
SET [TEST1]=' + '''' + convert(nvarchar(36), #TEST1) + '''' +',
[TEST2]=' + '''' +#TEST2 + '''' +',
[TEST3]=' + '''' + #TEST3 + '''' +',
[TEST4]='+ '''' + #TEST4 + '''' +',
[TEST5]=' + '''' + #TEST5 + '''' +',
[TEST6]=' + '''' + #TEST6 + '''' +
' WHERE [TEST1] =' + '''' + convert(nvarchar(36), TEST1 )+ '''' +
+ 'SELECT [TEST1] FROM
[' + #LINKED_SERVER_NAME + '].[' + #DATABASE_NAME + '].[Rev].[SOME_TABLE]
WHERE [TEST1] =' + '''' + convert(nvarchar(36), TEST1 )+ '''' +''
PRINT LEN(#SQL)
EXEC (#SQL)
COMMIT
TIA Experts!
Here's how you use ISNULL. If the first value is null, it will return the 2nd value.
SELECT #SQL = 'UPDATE [' + #LINKED_SERVER_NAME + '].[' + #DATABASE_NAME + '].[dbo].[SOME_TABLE]
SET [TEST1]=' + '''' + convert(nvarchar(36), ISNULL(#TEST1, '')) + '''' +',
[TEST2]=' + '''' +ISNULL(#TEST2, '') + '''' +',
[TEST3]=' + '''' + ISNULL(#TEST3, '') + '''' +',
...
etc...
You should use parametrized query. Here's an example:
DECLARE #sql nvarchar(max), #paramlist nvarchar(max)
SELECT #sql= 'UPDATE Table
SET Col1 = #Value1,
Col2 = #Value2
WHERE (1 = 1)'
SELECT #paramlist = '#Value1 nvarchar (256), #Value2 nvarchar (256)'
EXEC sp_executesql #sql, #paramlist, #Value1, #Value2