I need to perform update but with stored procedure I can't use It.So I m no choice then converting to function.
This is my Stored procedure.
alter Proc spIsUnique
#columnname nvarchar(max),
#tablename nvarchar(max)
As
Begin
EXEC ('select IIf (count(*)>1,''False'',''True'') as [IsUnique-check]
from '+#tablename+'
group by '+#columnname)
End
I try to convert it to inline function
create Function fn_IsUnique(
#columnname nvarchar(max),
#tablename nvarchar(max)
) returns table
As
return
select IIf (count(*)>1,'False','True') as [IsUnique-check]
from #tablename
group by #columnname
It throws me this error
Must declare the table variable "#tablename
Help me convert scored procedure to inline function.
Edited:-
If it is not possible to convert into inline function.
Any alternative way How can I use result of this stored procedure into update statement.
try This
CREATE FUNCTION dbo.FnRetCnt
(
#tablename nvarchar(max)
)
RETURNS BIT
AS
BEGIN
DECLARE #Ret BIT
DECLARE #t TABLE
(
Cnt INT
)
INSERT INTO #t
SELECT
SUM(st.row_count)
FROM
sys.dm_db_partition_stats st
WHERE
object_id = OBJECT_ID(#tablename)
IF EXISTS(SELECT 1 FROM #t WHERE Cnt>0)
SET #Ret = 0
ELSE
SET #Ret = 1
RETURN #Ret
END
go
SELECT
dbo.FnRetCnt('AddressType')
Related
My function is:
Create Function [dbo].[FindMaxRadif](#field nvarchar(15), #tbl nvarchar(15))
returns int
as
begin
declare #query int
set #query = 'select max('+ #field+') from '+ #tbl
return (#query)
end
when Execute this function with this command:
select dbo.FindMaxRadif('IdVehicle','TblVehicle')
I recive this error:
Conversion failed when converting the nvarchar value 'select
max(IdVehicle) from TblVehicle' to data type int.
how to fix it?
Dynamic SQL is not allowed in a User-Defined function. They are not allowed to make data changes, and prohibiting dynamic SQL helps enforce that. You can use a Stored Procedure instead, returning data either as a resultset:
create or alter procedure [dbo].[FindMaxRadif] #field nvarchar(15), #tbl nvarchar(15)
as
/*
create table a(i int)
insert into a(i) values (1),(2);
exec FindMaxRadif 'i','a'
*/
begin
declare #query nvarchar(max);
set #query = concat('select max(', quotename(#field), ') from ', quotename(#tbl));
--print #query
exec(#query);
end
or an output parameter
create or alter procedure [dbo].[FindMaxRadif2] #field nvarchar(15), #tbl nvarchar(15), #rv int output
as
/*
create table a(i int)
insert into a(i) values (1),(2);
declare #v int
exec FindMaxRadif2 'i','a', #v out
select #v
*/
begin
declare #query nvarchar(max);
set #query = concat('select #rv = max(', quotename(#field), ') from ', quotename(#tbl));
--print #query
exec sp_executesql #query, N'#rv int output', #rv = #rv output
end
Create Function fnRMatrixColorGet1(
#RMID varchar(20)
)
returns varchar(100)
as
begin
EXEC (N'SELECT ' + 'C'+#RMID + ' FROM vwemployeeget where empid='+#RMID)
return
end
As Gordon wrote in the comments, user defined functions in SQL Server can't execute dynamic SQL.
From Create User-defined Functions:
User-defined functions cannot make use of dynamic SQL or temp tables. Table variables are allowed.
However, you can create a stored procedure to do that:
CREATE PROCEDURE stpRMatrixColorGet1
(
#RMID varchar(20)
#MatrixColor varchar(100) OUTPUT
)
AS
DECLARE #Sql nvarchar(4000),
#Column sysname = N'C' + #RMID;
-- White list column name since it can't be parameterized
IF EXISTS
(
SELECT 1
FROM Information_Schema.Columns
WHERE Table_Name = 'vwemployeeget'
AND Column_Name = #Column
)
BEGIN
SET #SQL = N'SELECT #MatrixColor = QUOTENAME('+ #Column +') FROM vwemployeeget where empid = #RMID'
-- Safely execute dynamic SQL using sp_ExecuteSql
EXEC sp_ExecuteSql
#Sql,
N'#RMID varchar(20), #MatrixColor varchar(100) OUTPUT',
#RMID,
#MatrixColor OUTPUT
END
Is there any way to pass a tsql function a database name so it can perform selects on that database
ALTER function [dbo].[getemailjcp]
(
#DB_Name varchar(100)
)
Returns varchar(4000)
AS
BEGIN
DECLARE #out varchar (4000);
DECLARE #in varchar (1000);
Set #out =
(select substring
((select ';' + e.email from
(SELECT DISTINCT ISNULL(U.nvarchar4, 'NA') as email
FROM [#DB_Name].dbo.Lists ...
In order to create dynamic SQL statement you should store procedure. For example:
DECLARE #DynamicSQLStatement NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #FirstID BIGINT
SET #ParmDefinition = N'#FirstID BIGINT OUTPUT'
SET #DynamicSQLStatement=N' SELECT #FirstID=MAX(ID) FROM ['+#DatabaseName+'].[dbo].[SourceTable]'
EXECUTE sp_executesql #DynamicSQLStatement,#ParmDefinition,#FirstID=#FirstID OUTPUT
SELECT #FirstID
In this example:
#DatabaseName is the passed as parameter to your procedure.
#FirstID is output parameter - this value might be return from your procedure.
Here you can find more information about "sp_executesql":
http://msdn.microsoft.com/en-us/library/ms188001.aspx
a better solution might be to replace "#DatabaseName" (a char variable)with:
"DB_NAME(<#DBId>)".
You can then continue to pass in the db names, but 1st converting them to IDs in the fcn. Also kinda resolves the contradiction of building a SQL stmt w/ a char variable in it, if using "sp_executesql" to help guard against SQL injection ("DB_NAME()" isn't a variable/can't be substituted).
So you'd have this:
DECLARE #DynamicSQLStatement NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #FirstID BIGINT
DECLARE #DBId INT
SET #DBId = DB_ID(#Db_Name) --raise the proper security/robustness** concern if this doesn't resolve.
SET #ParmDefinition = N'#FirstID BIGINT OUTPUT'
SET #DynamicSQLStatement=N' SELECT #FirstID=MAX(ID) FROM ['+DB_NAME(#DBId)+'].[dbo].[SourceTable]'
I'm trying to combine a result mixed with some SELECTs.
I wanted to set #result combined with the result of [proc_Get_Frame_CourseNum] procedure but It didn't work.
declare #str varchar(300)
declare #result varchar(200)
declare #temp varchar(20)
declare #i int
set #str='110,120,130,140'
set #result=''
set #temp=''
set #i=0
while #i<len(#str)/4+1
begin
set #temp=substring(#str,1,3)
set #str=substring(#str,2,len(#str))
set #result=#result+ exec [proc_Get_Frame_CourseNum] #temp
set #i=#i+1
end
select #temp
Personally, I'd make use of output variables
CREATE PROCEDURE proc_Get_Frame_CourseNum
#temp varchar(20),
#outValue varchar(50) OUTPUT
AS
BEGIN
--do stuff
--before you leave the method or do your final SELECT
SET #outValue = 'whatever your result is'
--more stuff
END
Then in your code, you just go:
DECLARE #outValue VARCHAR(20)
-- rest of your code
EXEC [proc_Get_Frame_CourseNum] #temp, #outValue OUT
SET #result = #result + #outValue
Alternatively, you could just dump the results of the SP into a temp table, then read from it into your #Result variable.
You can't interpolate the result of one procedure by appending it.
I am assuming now that [proc_Get_Frame_CourseNum] returns a scalar result.
So run exec [proc_Get_Frame_CourseNum] #temp in another line of batch (before set #result = #result + call)
Your query should look like,
declare #scalarResult = exec [proc_Get_Frame_CourseNum] #temp
set #result=#result+ #scalarResult
Can anyone tell how correct the following code below. Iam tryin to create a stored procedure that returns the rowcount of a table whose name is passed to it.
CREATE PROCEDURE spROWCOUNTER
(
#tablename nvarchar(20)
#rowCountVal int OUTPUT
)
AS
DECLARE #strQuery nvarchar(300)
SET #strQuery = 'SELECT #rowCountVal=COUNT(*) FROM '+#tablename
EXEC(#strQuery)
RETURN #rowCountVal
ERROR MESSAGE :
Incorrect syntax near '#rowCountVal'
Must declare scalar variable '#tablename'
Must declare scalar variable '#rowCountVal'
whereas the code below works fine
ALTER PROCEDURE spROWCOUNTER
(
#rowCountVal int OUTPUT
)
AS
SELECT #rowCountVal=COUNT(*) FROM DEFECT_LOG
RETURN #rowCountVal
CREATE PROCEDURE spROWCOUNTER
#tablename nvarchar(20),
#rowCountVal int OUTPUT
AS
SELECT #rowCountVal = ISNULL(SUM(spart.rows), 0)
FROM sys.partitions spart
WHERE spart.object_id = object_id(#tablename) AND spart.index_id < 2
RETURN #rowCountVal
The syntax problem is easy to solve. There is a missing comma (",") between your parameters. Insert the comma and the stored procedure compiles:
( #tablename nvarchar(20), #rowCountVal int OUTPUT )
Then, there is the major problem: you can't access the #rowCountVal parameter inside the EXEC statement. To solve this problem, you could use the built-in stored procedure sp_executesql.
Read this good article written by the SQL Server MVP Erland Sommarskog.
By the way: you don't have to "return" a variable. Return values are normally used for returning some status values. If you pass an output parameter, it will be automatically returned.
I would use sp_executesql instead of exec. Then you can pass in #rowCountVal as an output variable into the dynamic sql.
create PROCEDURE spROWCOUNTER
(
#tablename nvarchar(20),
#rowCountVal int OUTPUT
)
AS
DECLARE #strQuery nvarchar(300)
SET #strQuery = 'SELECT #rowCountVal = COUNT(*) FROM '+#tablename
exec sp_executesql #strQuery, N'#tablename nvarchar(20), #rowCountVal int OUTPUT', #tablename = #tablename, #rowCountVal = #rowCountVal output
RETURN #rowCountVal
if you want the row count as a function you can also check Speeding up the Performance of Table Counts in SQL Server 2005
Provided in the article function is apparently faster than calling count(*) for very big tables.
In an execute statement, you can use a temporary table to share data:
CREATE PROCEDURE spROWCOUNTER
#tablename nvarchar(20),
#rowCountVal int OUTPUT
AS
CREATE TABLE #Result( Rows INT )
EXEC( 'INSERT INTO #Result( Rows ) SELECT COUNT(*) FROM ' + #tablename )
SELECT #rowCountVal = Rows FROM #Result
RETURN #rowCountVal
yes, i missed the comma. But even after that,the value doesn't get stored in #rowCountVal.
SET #strQuery = 'SELECT #rowCountVal=COUNT(*) *FROM '+ #tablename
EXEC(#strQuery)
the query doesnt return nor displays any value.
By the way, I thought of calling this proc from other stored-procedures to get rowcounts.
Will the following statement work :
set #rCount = exec spROWCOUNTER('DEFECT_LOG')