How to pass column name along with other parameters - mysql

I have below SPROC in which i am passing column name(value) along with other parameters(Place,Scenario).
ALTER PROCEDURE [dbo].[up_GetValue]
#Value varchar(20), #Place varchar(10),#Scenario varchar(20), #Number varchar(10)
AS BEGIN
SET NOCOUNT ON;
DECLARE #SQLquery AS NVARCHAR(MAX)
set #SQLquery = 'SELECT ' + #Value + ' from PDetail where Place = ' + #Place + ' and Scenario = ' + #Scenario + ' and Number = ' + #Number
exec sp_executesql #SQLquery
END
GO
when executing : exec [dbo].[up_GetValue] 'Service', 'HOME', 'Agent', '123697'
i am getting the below error msg
Invalid column name 'HOME'.
Invalid column name 'Agent'.
Do i need to add any thing in the sproc??

First: You tagged your question as mysql but I think your code is MSSQL.
Anyway, your problem is that you need to add quotes around each string valued parameter.
Like this:
alter PROCEDURE [dbo].[up_GetValue]
#Value varchar(20), #Place varchar(10),#Scenario varchar(20), #Number varchar(10)
AS BEGIN
SET NOCOUNT ON;
DECLARE #SQLquery AS NVARCHAR(MAX)
set #SQLquery = 'SELECT ' + QUOTENAME(#Value) + ' from PDetail where Place = ''' + #Place + ''' and Scenario = ''' + #Scenario + ''' and Number = ''' + #Number +''''
print #SQLquery
exec sp_executesql #SQLquery
END
GO
Update:
Use QUOTENAME to make sure it works.
QUOTENAME:
Returns a Unicode string with the delimiters added to make the input string a valid SQL Server delimited identifier.

You need to quote column names with ` (backtick) and string values with ".
set #SQLquery = 'SELECT `' + #Value + '` from PDetail where Place = "' + #Place + '" and Scenario = "' + #Scenario + '" and Number = ' + #Number

Try using a prepared statement instead of concatinating the string.
Example:
PREPARE stmt1 FROM 'SELECT ? from PDetail where Place = ? and Scenario = ? and Number = ?;
EXECUTE stmt1 USING #Value, #Place, #Scenario, #Number;

Related

SQL - check if column exists within stored procedure (table is variable)

This doesn't seem to have been answered anywhere (although very similar cases have been answered)...
I have an issue where I am trying to update a column's value in a table within a stored procedure. However, I pass more than one table to this stored procedure and some tables have a certain column and others don't. Thus I need to check if the column exists before I run this update. Now, because it's in a stored procedure, SQL seems to be parsing the entire chunk of code up front and complains that this column doesn't exist.
Code:
IF COL_LENGTH(''DBName' + #date+ '..' + #TableName + #date+''', ''ColumnName' + #specifictocolumn + 'restofcolumnname'') IS NOT NULL
update DBName' + #date+ '..' + #TableName + #date+ ' set ColumnName' + #specifictocolumn + 'restofcolumnname = 0
Alternatively
IF EXISTS(SELECT 1 FROM sys.columns WHERE Name = N''ColumnName' + #specifictocolumn + 'restofcolumnname '' AND Object_ID = Object_ID(N''DBName' + #date+ '..' + #TableName + #date+'''))
update DBName' + #date+ '..' + #TableName + #date+ ' set ColumnName' + #specifictocolumn + 'restofcolumnname = 0
Both of these give the error (column name removed for IP purposes):
Msg 207, Level 16, State 1, Line 6
Invalid column name 'ColumnName'.
There is a question on stack overflow called "Disable TSQL script check" that I looked at, but they suggest that you call the check of the column outside of the dynamic sql and then only execute if it passes the check. This won't work for me because part of the if-statement has variables in it that need to be in dynamic sql.
You can still split the dynamic SQL in 2 parts:
check if the column exists
do the actual update when 1. returns true
you'll probably want to use sp_executesql for this and an OUTPUT parameter.
Something along the lines of this:
DECLARE #sql nvarchar(max),
#result int
SELECT #sql = 'SELECT #col_length = COL_LENGTH(''DBName' + #date + '..' + #TableName + #date + ''', ''ColumnName' + #specifictocolumn + 'restofcolumnname'')'
EXEC sp_executesql #stmt = #sql,
#params = N'#col_length int OUTPUT',
#col_length = #result OUTPUT
IF #result IS NOT NULL
BEGIN
EXEC ('update DBName' + #date+ '..' + #TableName + #date+ ' set ColumnName' + #specifictocolumn + 'restofcolumnname = 0')
END
Or you could go 'dynamic inside dynamic', but will become a mess very quickly.

Incorrect syntax near 'REPLACE'

the following SQL statement shows solid results with PRINT but with EXEC, gives me Incorrect syntax near 'REPLACE'
USE EPDB
DECLARE #Table as nvarchar(100)
DECLARE #Column as nvarchar(100)
DECLARE #Select as nvarchar(375)
DECLARE #Where as nvarchar(275)
SET #Table = 'TableABC'
SET #Column = 'ColumnABC'`enter code here`
SET #Select = 'SELECT * FROM INFORMATION_SCHEMA.COLUMNS'
SET #Where = 'CRITERIA = ''VALUE'''
-- EXEC ('SELECT * FROM INFORMATION_SCHEMA.COLUMNSWHERETABLE_NAME = ' + #Table + '''')
PRINT #Select + ' WHERE ' + REPLACE(REPLACE(#Where,'CRITERIA','TABLE_NAME'),'VALUE',#Table)
EXEC (#Select + ' WHERE ' + REPLACE(REPLACE(#Where,'CRITERIA','TABLE_NAME'),'VALUE',#Table))
not sure what is going on here
Try this:
DECLARE #sSQL varchar(1000)
SET #sSQL = #Select + ' WHERE ' + REPLACE(REPLACE(#Where,'CRITERIA','TABLE_NAME'),'VALUE',#Table)
EXEC (#sSQL)
I believe EXEC() accepts either string variable or a string constant, but not combination.

SQL Server Execute update result sets from dynamic query writer

This link is where I found part of an answer to my problem.
SQL replace all NULLs
Simon posted
"Be a boss. Write something like:
select 'update ' + table_name + ' set [' + column_name + '] = '''' where [' + column_name + '] is null'
from tempdb.information_schema.columns
where table_name = 'YourTableName'
It'll spit out a big ol' query for you.
You're welcome"
But I would like to know if there a way to use the results set in a parameter and execute all of the update statements.
I tried something like this
DECLARE #sql2 AS NVARCHAR(MAX) = N'
SELECT ''UPDATE '' + table_name + '' SET ['' + column_name + ''] = '''''''' WHERE ['' + column_name + ''] IS NULL''
FROM tempdb.information_schema.columns
WHERE table_name = ''##tempF'''
EXEC sp_executesql #stmt = #sql2;
DECLARE #sql3 AS NVARCHAR(MAX);
SET #sql3 = (SELECT #sql2);
EXEC sp_executesql #stmt = #sql3;
but it two result sets like listed below:
UPDATE ##tempF SET [claimid] = '' WHERE [claimid] IS NULL
UPDATE ##tempF SET [hdr_status] = '' WHERE [hdr_status] IS NULL
UPDATE ##tempF SET [memid] = '' WHERE [memid] IS NULL
Many thanks to you all.
Cheers!
Tim
Like this
--initialize variables
DECLARE #UpdateColumns varchar(max) = ''
DECLARE #IsNullColumns varchar(max) = ''
SELECT
#UpdateColumns = #UpdateColumns + ',[' + COLUMN_NAME + '] = ISNULL([' + COLUMN_NAME + '],'''')',
#IsNullColumns = #IsNullColumns + ' OR [' + COLUMN_NAME + '] IS NULL'
FROM tempdb.information_schema.columns
WHERE table_name = '##tempF'
This should fill in the two variables with the following values:
#UpdateColumns = ',[claimid] = ISNULL([claimid],''''),[hdr_status] = ISNULL([hdr_status],''''),[memid] = ISNULL([memid],'''')'
#IsNullColumns = ' OR [claimid] IS NULL OR [hdr_status] IS NULL OR [memid] IS NULL'
Then you need to assemble it all (remember to remove the first characters of each of the variables (the STUFF function is great for that):
DECLARE #qry varchar(max) = 'UPDATE ##tempF SET '
+ STUFF(#UpdateColumns,1,1,'') + ' WHERE '
+ STUFF(#IsNullColumns,1,4,'') --the 4 in here is to get rid of ' OR ' (4 chars)
EXEC(#qry)

insert command SQL server -identity Pkey autoincrement - column name by type , in "where condition"

i would like to alter a stored procedure so i will not suplly the identity column name
INSERT INTO tablName ..... WHERE IDENTITY_Column = 10
can i tell sql server managment studio to just refer to the IDENTITY column so it will find
it by its type which is (at least in my tables a default) autoincremet PK ID type
You haven't really given enough code for us to see what you are trying to do but from the snippet in the question.
WHERE IDENTITY_Column = 10
You can just use
WHERE $IDENTITY = 10
for that (to filter against an identity column without specifying the name).
If you do actually need to lookup the column name then an easier way, avoiding deprecated views is
SELECT name
FROM sys.identity_columns
WHERE object_id = object_id('dbo.YourTable')
found this information by now .
that is the plain and simple version .
declare #tblName sysname = '______'--<== enter a table name
declare #NameOfIDColumn sysname =
(
SELECT Name
FROM syscolumns
WHERE COLUMNPROPERTY( id ,name, 'IsIdentity') = 1 and OBJECT_NAME(id)= #tblName )
select #NameOfIDColumn AS 'result'
you could add this as an option to display last row of a table soretd by its record#
declare #query VARCHAR(100) = 'Select Top 1 * FROM '+ #tblName +' Order BY ' + #IdentColumnName + ' desc' ;
EXEC (#query);
and to play around or even make it as a test page in a .net project
make this one as a stored proc that will outpout a message to a test page .
declare #tblName sysname = '______'--<== enter a table name
declare #IdentColumnName sysname =
(
SELECT Name
FROM syscolumns
WHERE COLUMNPROPERTY( id ,name, 'IsIdentity') = 1 and OBJECT_NAME(id)= #tblName )
declare #result VARCHAR (50) = #tblName + ' Identity Column is ' + #IdentColumnName;
select #result AS 'result'
and with a shorter version of "idntity column search", by Martin Smith
declare #tblName sysname = '______'--<== enter a table name
declare #IdentColumnName sysname =
(SELECT name FROM sys.identity_columns WHERE object_id = object_id(#TableName))
declare #result VARCHAR (50) = #tblName + ' Identity Column is ' + #IdentColumnName;
select #result AS 'result'
this is related to a table copy trick i was trying to pull via stored procedure.
USE [YourDataBaseName]
GO
/****** Object: StoredProcedure [dbo].[Utils_TableRowCopy] Script Date: 10/03/2012 18:26:58 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Utils_TableRowCopy](
#TableName VARCHAR(50) ,
#RowNumberToCopy INT
)
AS
BEGIN
declare #RowIdentity sysname =
(
SELECT name FROM sys.identity_columns WHERE object_id = object_id(#TableName)
)
DECLARE #columns VARCHAR(5000), #query VARCHAR(8000);
SET #query = '' ;
SELECT #columns =
CASE
WHEN #columns IS NULL THEN column_name
ELSE #columns + ',' + column_name
END
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (
TABLE_NAME = LTRIM(RTRIM(#TableName))
AND
column_name <> LTRIM(RTRIM(#RowIdentity))
);
SET #query = 'INSERT INTO ' + #TableName + ' (' + #columns + ') SELECT ' + #columns + ' FROM ' + #TableName + ' WHERE ' + #RowIdentity + ' = ' + CAST(#RowNumberToCopy AS VARCHAR);
--SELECT SCOPE_IDENTITY();
declare #query2 VARCHAR(100) = ' Select Top 1 * FROM '+ #TableName +' Order BY ' + #RowIdentity + ' desc' ;
EXEC (#query);
EXEC (#query2);
END

sql update with dynamic column names

EDIT: Database names have been modified for simplicity
I'm trying to get some dynamic sql in place to update static copies of some key production tables into another database (sql2008r2). The aim here is to allow consistent dissemination of data (from the 'static' database) for a certain period of time as our production databases are updated almost daily.
I am using a CURSOR to loop through a table that contains the objects that are to be copied into the 'static' database.
The prod tables don't change that frequently, but I'd like to make this somewhat "future proof" (if possible!) and extract the columns names from INFORMATION_SCHEMA.COLUMNS for each object (instead of using SELECT * FROM ...)
1) From what I have read in other posts, EXEC() seems limiting, so I believe that I'll need to use EXEC sp_executesql but I'm having a little trouble getting my head around it all.
2) As an added extra, if at all possible, i'd also like to exclude some columns for particular tables (structures vary slightly in the 'static' database)
here's what i have so far.
when executed, #colnames returns NULL and therefore #sql returns NULL...
could someone guide me to where i might find a solution?
any advice or help with this code is much appreciated.
CREATE PROCEDURE sp_UpdateRefTables
#debug bit = 0
AS
declare #proddbname varchar(50),
#schemaname varchar(50),
#objname varchar(150),
#wherecond varchar(150),
#colnames varchar(max),
#sql varchar(max),
#CRLF varchar(2)
set #wherecond = NULL;
set #CRLF = CHAR(10) + CHAR(13);
declare ObjectCursor cursor for
select databasename,schemaname,objectname
from Prod.dbo.ObjectsToUpdate
OPEN ObjectCursor ;
FETCH NEXT FROM ObjectCursor
INTO #proddbname,#schemaname,#objname ;
while ##FETCH_STATUS=0
begin
if #objname = 'TableXx'
set #wherecond = ' AND COLUMN_NAME != ''ExcludeCol1'''
if #objname = 'TableYy'
set #wherecond = ' AND COLUMN_NAME != ''ExcludeCol2'''
--extract column names for current object
select #colnames = coalesce(#colnames + ',', '') + QUOTENAME(column_name)
from Prod.INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = + QUOTENAME(#objname,'') + isnull(#wherecond,'')
if #debug=1 PRINT '#colnames= ' + isnull(#colnames,'null')
--replace all data for #objname
--#proddbname is used as schema name in Static database
SELECT #sql = 'TRUNCATE TABLE ' + #proddbname + '.' + #objname + '; ' + #CRLF
SELECT #sql = #sql + 'INSERT INTO ' + #proddbname + '.' + #objname + ' ' + #CRLF
SELECT #sql = #sql + 'SELECT ' + #colnames + ' FROM ' + #proddbname + '.' + #schemaname + '.' + #objname + '; '
if #debug=1 PRINT '#sql= ' + isnull(#sql,'null')
EXEC sp_executesql #sql
FETCH NEXT FROM ObjectCursor
INTO #proddbname,#schemaname,#objname ;
end
CLOSE ObjectCursor ;
DEALLOCATE ObjectCursor ;
P.S. i have read about sql injection, but as this is an internal admin task, i'm guessing i'm safe here!? any advice on this is also appreciated.
many thanks in advance.
You have a mix of SQL and dynamic SQL in your query against information_schema. Also QUOTENAME isn't necessary in the where clause and will actually prevent a match at all, since SQL Server stores column_name, not [column_name], in the metadata. Finally, I'm going to change it to sys.columns since this is the way we should be deriving metadata in SQL Server. Try:
SELECT #colnames += ',' + name
FROM Prod.sys.columns
WHERE OBJECT_NAME([object_id]) = #objname
AND name <> CASE WHEN #objname = 'TableXx' THEN 'ExcludeCol1' ELSE '' END
AND name <> CASE WHEN #objname = 'TableYy' THEN 'ExcludeCol2' ELSE '' END;
SET #colnames = STUFF(#colnames, 1, 1, '');