must declare the scalar variable #columns - sql

I've got error:
Must declare the scalar variable #columns
Where is the problem? Thank you
ALTER PROCEDURE CreateTable
#tabname nvarchar(max)
as
declare #columns nvarchar(max) = null;
declare #sql nvarchar(max) = null;
select #columns=coalesce(#columns + ', ')
+colname
+ ' '
+coltype
from x_column
where colname is not null
and tabname=#tabname
order by colnum;
set #sql =IF NOT EXISTS (SELECT * FROM sys.objects WHERE
object_id=OBJECT_ID(N'[#tabname]') AND type in (N'U'))
create table ' + #tabname + ' (' + #columns + ');
print #sql;
-- execute create table
exec sp_sqlexec #sql;
GO

Try like this,
ALTER PROCEDURE CreateTable #tabname NVARCHAR(max)
AS
DECLARE #columns NVARCHAR(max) = NULL;
DECLARE #sql NVARCHAR(max) = NULL;
SELECT #columns = coalesce(#columns, ', ') + colname + ' ' + coltype
FROM x_column
WHERE colname IS NOT NULL
AND tabname = #tabname
ORDER BY colnum;
SET #sql = 'IF NOT EXISTS (SELECT * FROM sys.objects WHERE
object_id=OBJECT_ID(N[' + #tabname + ']) AND type in (N''U''))
create table [' + #tabname + '] (' + #columns + ');'
PRINT #sql;
-- execute create table
EXEC sp_sqlexec #sql;
GO

Syntax error with coalesce and for #sql the data is not loaded properly
So the below script will work:
alter PROCEDURE CreateTable
#tabname nvarchar(max)
as
declare #columns nvarchar(max) = null;
declare #sql nvarchar(max) = null;
select #columns = coalesce(#columns , ', ') + colname + ' ' + coltype
from x_column
where colname is not null
and tabname = #tabname
order by colnum;
set #sql = 'IF NOT EXISTS ( SELECT * FROM sys.objects WHERE
object_id = OBJECT_ID(N[' + #tabname + ']) AND type in (N''U''))
create table ' + #tabname + ' (' + #columns + ');'
print #sql;
-- execute create table
exec sp_sqlexec #sql;
GO

Change your query like this:
ALTER PROCEDURE CreateTable
#tabname nvarchar(max)
as
declare #columns nvarchar(max) = null;
declare #sql nvarchar(max) = null;
SELECT #columns = STUFF((SELECT ',' + colname + ' ' + coltype
FROM x_column
WHERE colname IS NOT NULL
AND tabname = #tabname
ORDER BY colnum
FOR XML PATH('')),1,1,'')
set #sql ='IF NOT EXISTS (SELECT * FROM sys.objects WHERE
object_id=OBJECT_ID(N['+#tabname+']) AND type in (N''U''))
create table [' + #tabname + '] (' + #columns + ');'
print #sql;
-- execute create table
exec sp_sqlexec #sql;
GO

use this
set #sql ='IF NOT EXISTS (SELECT * FROM sys.objects WHERE
object_id=OBJECT_ID('+#tabname+') AND type in (''U''))
create table ' + #tabname + ' (' + #columns + ')';`

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 + ''''

How can I modify a stored procedure to include multiple tables

Hi this Stored Procedure works for one table, I wondered can it be expanded to more than one table so that the returned values technically searches across multiple tables. I have read similar posts which cover an entire database but limiting to a small cluster of tables rather than having to do each manually.
Basically so the final execute runs this below basically going through all tables which start with LZO_AE
#table_name ='LZO_AE%'
IF NOT EXISTS (
SELECT *
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_NAME = 'spSearchStringInTable'
AND ROUTINE_TYPE = 'PROCEDURE'
)
EXECUTE ('CREATE PROCEDURE dbo.spSearchStringInTable AS SET NOCOUNT ON;');
GO
ALTER PROCEDURE spSearchStringInTable (
#SearchString NVARCHAR(MAX)
,#Table_Schema SYSNAME = 'dbo'
,#Table_Name SYSNAME
)
AS
BEGIN
DECLARE #Columns NVARCHAR(MAX)
,#Cols NVARCHAR(MAX)
,#PkColumn NVARCHAR(MAX)
-- Get all character columns
SET #Columns = STUFF((
SELECT ', ' + QUOTENAME(Column_Name)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE IN (
'text'
,'ntext'
,'varchar'
,'nvarchar'
,'char'
,'nchar'
,'int'
)
AND TABLE_NAME = #Table_Name
AND TABLE_SCHEMA = #Table_Schema
ORDER BY COLUMN_NAME
FOR XML PATH('')
), 1, 2, '');
IF #Columns IS NULL -- no character columns
RETURN - 1;
-- Get columns for select statement - we need to convert all columns to nvarchar(max)
SET #Cols = STUFF((
SELECT ', CAST(' + QUOTENAME(Column_Name) + ' AS nvarchar(max)) COLLATE DATABASE_DEFAULT AS ' + QUOTENAME(Column_Name)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE IN (
'text'
,'ntext'
,'varchar'
,'nvarchar'
,'char'
,'nchar'
,'int'
)
AND TABLE_NAME = #Table_Name
AND TABLE_SCHEMA = #Table_Schema
ORDER BY COLUMN_NAME
FOR XML PATH('')
), 1, 2, '');
SET #PkColumn = STUFF((
SELECT N' + ''|'' + ' + ' CAST(' + QUOTENAME(CU.COLUMN_NAME) + ' AS nvarchar(max)) COLLATE DATABASE_DEFAULT '
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS CU ON TC.CONSTRAINT_TYPE = 'PRIMARY KEY'
AND TC.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
WHERE TC.TABLE_SCHEMA = #Table_Schema
AND TC.TABLE_NAME = #Table_Name
ORDER BY CU.ORDINAL_POSITION
FOR XML PATH('')
), 1, 9, '');
IF #PkColumn IS NULL
SELECT #PkColumn = 'CAST(NULL AS nvarchar(max))';
-- set select statement using dynamic UNPIVOT
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = 'SELECT *, ' + QUOTENAME(#Table_Schema, '''') + ' AS [Table Schema], ' + QUOTENAME(#Table_Name, '''') + ' AS [Table Name]' + ' FROM
(SELECT ' + #PkColumn + ' AS [PK Column], ' + #Cols + ' FROM ' + QUOTENAME(#Table_Schema) + '.' + QUOTENAME(#Table_Name) + ' ) src UNPIVOT ([Column Value] for [Column Name] IN (' + #Columns + ')) unpvt
WHERE [Column Value] LIKE ''%'' + #SearchString + ''%'''
--print #SQL
EXECUTE sp_ExecuteSQL #SQL
,N'#SearchString nvarchar(max)'
,#SearchString;
END
GO
execute
dbo.spSearchStringInTable
#SearchString = N'410605003',
#table_schema = 'dbo',
#table_name ='LZO_AETRIAGETREATMENTHISTORY'
You could use a CURSOR to retrieve the matching table names and then process each one in a loop. For example,
ALTER PROCEDURE [dbo].[multi_table_test] AS
BEGIN
SET NOCOUNT ON;
DECLARE #table_pattern NVARCHAR(max);
DECLARE #table_name NVARCHAR(max);
DECLARE #sql NVARCHAR(max)
DECLARE #output_table TABLE (table_name NVARCHAR(max), row_count INT);
DECLARE #row_count INT;
SET #table_pattern = N'LZO_AE%';
DECLARE table_list CURSOR FOR
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE #table_pattern;
OPEN table_list;
FETCH NEXT FROM table_list INTO #table_name;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = N'SELECT #n = (SELECT COUNT(*) FROM [' + #table_name + N'])';
EXEC sp_executesql #sql, N'#n INT OUTPUT', #n = #row_count OUTPUT;
INSERT INTO #output_table (table_name, row_count) VALUES (#table_name, #row_count);
FETCH NEXT FROM table_list INTO #table_name;
END
CLOSE table_list;
DEALLOCATE table_list;
SELECT table_name, row_count FROM #output_table;
END
returns this
table_name row_count
---------- ---------
LZO_AE01 3
LZO_AE02 5

Modify columns using stored procedure in SQL Server

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