How to pass list of string to stored procedure - asp.net

public DataSet ViewQuizDetails(List<string> name)
{
DataSet dsGrades = null;
var dbCon = new DBConnection("Quiz");
foreach(string val in name)
{
dbCon.AddParameter("#name", val);
dsGrades = dbCon.Execute_DataSet("spViewQuizDetails", null);
}
return dsGrades;
}
ALTER PROCEDURE [dbo].[spViewQuizDetails]
-- Add the parameters for the stored procedure here
#name varchar(30)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
--SELECT * FROM QuizDetails INNER JOIN Elearning
--ON QuizDetails.ElearningId=Elearning.ElearningId ;
SELECT *
FROM QuizDetails INNER JOIN Elearning
ON QuizDetails.ElearningId=Elearning.ElearningId where ElearningName=#name
END
When I pass multiple values I'm getting the following error.
Error received: Procedure or function spViewQuizDetails has too many arguments
specified.

Pass your stored procedure a parameter with names concatinated .
Build this concatinated name string in your C# code
Declare #Name VARCHAR(1000) = 'Name1,Name2,Name3';
ALTER PROCEDURE [dbo].[spViewQuizDetails]
-- Add the parameters for the stored procedure here
#name VARCHAR(1000)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #xml xml;
set #xml = N'<root><r>' + replace(#name,',','</r><r>') + '</r></root>'
-- Insert statements for procedure here
--SELECT * FROM QuizDetails INNER JOIN Elearning ON QuizDetails.ElearningId=Elearning.ElearningId ;
SELECT * FROM QuizDetails
INNER JOIN Elearning
ON QuizDetails.ElearningId = Elearning.ElearningId
where ElearningName IN (select t.value('.','varchar(max)')
from #xml.nodes('//root/r') as a(t) )
END

Related

Teradata Procedure Locks a Log Table

I am trying to get around a problem where the following SP locks the log table DWH_METADATA.LOG_TABLE and the lock is released only when the DELETE ALL and INSERT-SELECT statements are executed. This procedure chokes the whole ETL process. Moreover, this procedure is called via IBM Data Stage Sequence.
Below is the procedure code:
REPLACE PROCEDURE DWH.HIST_PROC (OUT RETURN_MSG VARCHAR(100))
BEGIN
/**********************************
* DECALRE VARIABLES *
**********************************/
DECLARE PJ_RID INTEGER;
DECLARE MS_Name VARCHAR(100);
DECLARE JS_Name VARCHAR(100);
DECLARE JT_Name VARCHAR(100);
DECLARE PJ_Domain VARCHAR(100);
DECLARE JS_Timestamp TIMESTAMP(0);
DECLARE Script_Name VARCHAR(500);
DECLARE Procedure_Name VARCHAR(100);
DECLARE JS_No INTEGER;
DECLARE SS_Ts TIMESTAMP(0);
DECLARE SR_Processed INTEGER;
/***********************************
* EXCEPTION HANDLING *
***********************************/
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
UPDATE DWH_METADATA.LOG_TABLE
SET
JOB_STATUS = SQLCODE,
STEP_END_TS = CURRENT_TIMESTAMP(0),
JOB_END_TIMESTAMP = CURRENT_TIMESTAMP(0)
WHERE JOB_RUN_ID = PJ_RID
AND STEP_NO = JS_No
AND JOB_NAME = JS_Name;
END;
/**********************************
* SET VARIABLES *
**********************************/
SET MS_Name = 'A Value';
SET JS_Name='A Value';
SET JT_Name = 'A Value';
SET PJ_Domain = 'A Value';
SET JS_Timestamp = CURRENT_TIMESTAMP(0);
SET Script_Name = 'A Value';
SET Procedure_Name = 'A Value';
SET SS_Ts = CURRENT_TIMESTAMP(0);
SET JS_No = 0;
SET RETURN_MSG = 'Failure';
--------------------------------------------------------
--Insert log for step 0
INSERT INTO DWH_METADATA.LOG_TABLE
(
DWH_METADATA.LOG_TABLE.JOB_RUN_ID,
DWH_METADATA.LOG_TABLE.STEP_NO,
DWH_METADATA.LOG_TABLE.MASTER_SEQ_NAME ,
DWH_METADATA.LOG_TABLE.JOB_NAME ,
DWH_METADATA.LOG_TABLE.TABLE_NAME,
DWH_METADATA.LOG_TABLE.JS_Timestamp ,
DWH_METADATA.LOG_TABLE.JOB_END_TIMESTAMP ,
DWH_METADATA.LOG_TABLE.SS_Ts ,
DWH_METADATA.LOG_TABLE.STEP_END_TS ,
DWH_METADATA.LOG_TABLE.JOB_STATUS ,
DWH_METADATA.LOG_TABLE.JOB_DOMAIN ,
DWH_METADATA.LOG_TABLE.SCRIPT_NAME ,
DWH_METADATA.LOG_TABLE.PROCEDURE_NAME ,
DWH_METADATA.LOG_TABLE.RECORDS_PROCESSED
)
VALUES
(:PJ_RID, :JS_No, :MS_Name, :JS_Name, :JT_Name,
:JS_Timestamp, NULL, :SS_Ts, NULL, NULL, :PJ_Domain, :Script_Name, :Procedure_Name, NULL
);
-----------------------------------------------------------------------------------------------------------------
LOCKING ROW FOR ACCESS
SEL COALESCE(MAX(JOB_RUN_ID),0) + 1
FROM DWH_METADATA.LOG_TABLE
WHERE JOB_NAME = :JS_Name
AND Job_Domain = :PJ_Domain
INTO :PJ_RID;
/********************************** DELETE/INSERT RTD_DATA *************************************************/
--Insert log for step 1
SET JS_No = JS_No + 1 ;
SET JT_Name = 'DWH.HISTORY_TABLE ';
SET SS_Ts = CURRENT_TIMESTAMP(0);
INSERT INTO DWH_METADATA.LOG_TABLE
VALUES( :PJ_RID, :JS_No, :MS_Name, :JS_Name, :JT_Name, :JS_Timestamp,
NULL, :SS_Ts, NULL, NULL, :PJ_Domain, :Script_Name, :Procedure_Name, NULL);
DELETE FROM DWH.HISTORY_TABLE ALL;
INSERT INTO DWH.HISTORY_TABLE
(
COLUMNLIST
)
SELECT
SI.COLUMNS,
S2.COLUMNS,
.
.
.
FROM SOMETABLE1 S1
INNER JOIN SOMETABLE2 S2
ON S1.ID = S2.ID
.
.
.
.;
--Update log for step 1
SET SR_Processed = ACTIVITY_COUNT;
UPDATE DWH_METADATA.LOG_TABLE
SET
JOB_STATUS = SQLCODE,
STEP_END_TS = CURRENT_TIMESTAMP(0),
JOB_END_TIMESTAMP = CURRENT_TIMESTAMP(0),
RECORDS_PROCESSED = :SR_Processed
WHERE JOB_RUN_ID = PJ_RID
AND STEP_NO = JS_No
AND JOB_DOMAIN = PJ_Domain
AND PROCEDURE_NAME = Procedure_Name
AND "TABLE_NAME"=JT_Name;
---------------------------------------------------------------------------------------
SET RETURN_MSG = 'Success' ;
END;
Based on same logic, many other stored procedures are executing on daily basis without any such issue. I am unable to understand, why this procedure locks the log table although both of its' insert statements have been executed.
I have tried to execute the individual DML statements in BT and ET, and doing such did not have any impact and the issue persisted. Moreover, I have optimized the underlying INSERT-SELECT. It has reduced the exeution time significantly but the locking is still occurring.
Anyone please, help me pinpoint why this issue is ocurring.
EDIT: Structure of log table.
CREATE MULTISET TABLE DWH_METADATA.LOG_TABLE ,FALLBACK ,
NO BEFORE JOURNAL,
NO AFTER JOURNAL,
CHECKSUM = DEFAULT,
DEFAULT MERGEBLOCKRATIO,
MAP = TD_MAP1
(
JOB_RUN_ID INTEGER,
STEP_NO INTEGER,
MASTER_SEQ_NAME VARCHAR(50) CHARACTER SET LATIN NOT CASESPECIFIC,
JOB_NAME VARCHAR(200) CHARACTER SET LATIN NOT CASESPECIFIC,
TABLE_NAME VARCHAR(50) CHARACTER SET LATIN NOT CASESPECIFIC,
JOB_START_TIMESTAMP TIMESTAMP(6),
JOB_END_TIMESTAMP TIMESTAMP(6),
STEP_START_TS TIMESTAMP(0),
STEP_END_TS TIMESTAMP(0),
JOB_STATUS INTEGER,
JOB_DOMAIN VARCHAR(200) CHARACTER SET LATIN NOT CASESPECIFIC,
SCRIPT_NAME VARCHAR(100) CHARACTER SET LATIN NOT CASESPECIFIC,
PROCEDURE_NAME VARCHAR(100) CHARACTER SET LATIN NOT CASESPECIFIC,
RECORDS_PROCESSED DECIMAL(18,0))
PRIMARY INDEX ( JOB_NAME ,TABLE_NAME ,JOB_START_TIMESTAMP );

What is the SQL Server equivalent of EXECUTE IMMEDIATE INTO in Oracle

What is the SQL Server equivalent of EXECUTE IMMEDIATE INTO in Oracle?
E.g.
DECLARE QRY varchar(100);
val int;
BEGIN
QRY:='select count(*) from production.product';
**EXECUTE IMMEDIATE** QRY **into** val;
dbms_output.put_line(val);
END;
/
You can't set a scalar variable to the results of a dynamic query, but you can insert the results into a table variable. This works.
DECLARE #tbl TABLE (RowCnt INT NULL);
DECLARE
#QRY varchar(100);
BEGIN
SET #QRY = 'select <Aggregate Function> from tableName'; --Builds the dynamic query
INSERT #tbl
(
RowCnt
)
EXECUTE(#QRY); --Executes the query
SELECT
*
FROM #tbl;
END;
T-SQL equivalent for EXECUTE IMMEDIATE is Dynamic Sql.
DECLARE #intCount int
EXECUTE sp_executesql N'select #intCount=count(*) from product', N'#intCount int output', #intCount output;
Print(#intCount)
Alternatively, you can use
DECLARE #intCount2 int
SELECT #intCount2 = count(*) from product

how can i call stored procedure from the function in mariadb?

i want to get count of no.of rows present in table which i pass at runtime to a function.
i have created a procedure and function to execute dynamic queries. function will not allow dynamic query because i am calling procedure from function.
that procedure having dynamic query.
///////procedure///////
CREATE PROCEDURE bizopsgolddev.`test1`(tbnm varchar(100))
begin
declare sql_text varchar(200);
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SELECT CONCAT(sql_text, ' is not valid');
END;
set sql_text=concat('select count(*) from ',tbnm);
SET #SQL := sql_text;
PREPARE stmt FROM #SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
end;
//////function//////
DROP FUNCTION IF EXISTS xyz;
CREATE FUNCTION `xyz`(tname varchar(100)) RETURNS int(11)
begin
declare val int;
call test1(tname);
return 1;
end;
if i execute this //select xyz('axpdc')// it should return rows count
can any one tell me how can i get count by passing table name to function(in mariadb only)
As I understand the question, the solution would be a function that returns the row count of a table with it's name passed to the function as a parameter.
I think this could be done by querying the information_schema database in MariaDB. A function could look like this:
CREATE DEFINER = 'yourUsername'#'192.168.%'
FUNCTION testDataBase.fn_GetRowCount(tableName VARCHAR(128))
RETURNS int(11)
BEGIN
-- This could be a parameter if need it to be.
DECLARE databaseName varchar(40) DEFAULT 'testDataBase';
DECLARE result int DEFAULT -1;
SELECT t.TABLE_ROWS INTO result
FROM information_schema.TABLES t
WHERE t.TABLE_NAME = tableName
AND t.TABLE_SCHEMA = databaseName;
RETURN result;
END
In order for this to work the user mentioned as the definer must have read privilege to the TABLES table in the information_schema database, otherwise you might get an error (tbh, I don't know if this is necessary).
There is a lot of useful information to be grabbed from the information_schema database.

Error in stored procedure with string return type

ALTER PROCEDURE [dbo].[Signin_Check]
#uid varchar(50), #pwd varchar(50), #uname varchar(50) output
AS
IF EXISTS (SELECT * FROM threeLayer_user WHERE uid = #uid and pass = #pwd)
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT #uname = name
FROM threeLayer_user
WHERE uid = #uid and pass = #pwd
RETURN #uname
END
This stored procedure is throwing an error :
Conversion failed when converting the varchar value 'Saurav' to data type int.
Your code contains the line
return #uname
the return statement can only accept integer values. However, your #uname parameter is an output parameter, so you do not need to also return it. Just make sure that you specify OUTPUT when calling the sproc:
EXEC dbo.Signin_Check #uid, #password, #uname OUTPUT;
The SP doesn't seem to have bad code related to the error, could you check well the parameters being passed to the stored procedure (i.e. their order and their type)? The problem can be the values that you are passing and not the actual procedure.
Could you append to your post the code you are using when you invoke the stored procedure?
Are you sure that it's varchar column?
#uid varchar(50) / int
uid = #uid

SQL use comma-separated values with IN clause

I am developing an ASP.NET application and passing a string value like "1,2,3,4" into a procedure to select those values which are IN (1,2,3,4) but its saying "Conversion failed when converting the varchar value '1,2,3,4' to data type int."
Here is the aspx code:
private void fillRoles()
{
/*Read in User Profile Data from database */
Database db = DatabaseFactory.CreateDatabase();
DbCommand cmd = db.GetStoredProcCommand("sp_getUserRoles");
db.AddInParameter(cmd, "#pGroupIDs", System.Data.DbType.String);
db.SetParameterValue(cmd, "#pGroupIDs", "1,2,3,4");
IDataReader reader = db.ExecuteReader(cmd);
DropDownListRole.DataTextField = "Group";
DropDownListRole.DataValueField = "ID";
while (reader.Read())
{
DropDownListRole.Items.Add((new ListItem(reader[1].ToString(), reader[0].ToString())));
}
reader.Close();
}
Here is my procedure:
CREATE Procedure [dbo].[sp_getUserRoles](#pGroupIDs varchar(50))
AS BEGIN
SELECT * FROM CheckList_Groups Where id in (#pGroupIDs)
END
Here is a workaround I found to do what you are trying to achieve
CREATE Procedure [dbo].[sp_getUserRoles](
#pGroupIDs varchar(50)
)
As
BEGIN
SELECT * FROM CheckList_Groups Where (',' + #pGroupIDs +',' LIKE '%,' + CONVERT(VARCHAR, id) + ',%')
End
This gets your comma delimited list and compares it to the id's(which are represented like so ',1,', ',2,' etc) in the table using LIKE
If you dont want to use dynamic sql, the best way ive found is to create a function which turns a delimited string into a table, something like this works for an Integer list:
CREATE FUNCTION [dbo].[StringToIntList]
(#str VARCHAR (MAX), #delimeter CHAR (1))
RETURNS
#result TABLE (
[ID] INT NULL)
AS
BEGIN
DECLARE #x XML
SET #x = '<t>' + REPLACE(#str, #delimeter, '</t><t>') + '</t>'
INSERT INTO #result
SELECT DISTINCT x.i.value('.', 'int') AS token
FROM #x.nodes('//t') x(i)
ORDER BY 1
RETURN
END
Then use that in your sp:
CREATE Procedure [dbo].[sp_getUserRoles](
#pGroupIDs varchar(50)
)
As
BEGIN
SELECT * FROM CheckList_Groups Where id in (
SELECT ID FROM dbo.StringToIntList(#pGroupIds,',')
)
End
Sure it can't do that,
The generated query would be sth like this
SELECT * FROM CheckList_Groups Where id in ('1,2,3,4')
and sure it can't be executed.
you can build the query in your stored procedure then execute it with exec
'SELECT * FROM CheckList_Groups Where id in (' + #pGroupIDs + ')'
or
SELECT * FROM CheckList_Groups Where charindex(','+id+',' , #pGroupIDs)>0
but you first must add the ',' to start and end of your parameter in your c# code
It is not possible to put those values (the comma separated string) in a parameter-value.
What you'll have to do, is to create the SQL Statement in your stored procedure dynamically, by string concatenation. You'll have to execute it with the sp_executesql stored procedure then.
CREATE PROCEDURE [dbo].[getUserRoles]( #groupIds NVARCHAR(50) )
AS BEGIN
DECLARE #statement NVARCHAR(255)
SELECT #statement = N'SELECT * FROM CheckList_Groups Where id in ( ' + #pGroupIDs + N')'
execute sp_executesql #statement
END
Also, not that I named the SP getUserRoles instead of sp_getUserRoles.
The reason is very simple: when you execute a stored procedure whose name starts with sp_, then SQL Server will first query the master database to find that stored procedure, which causes a performance hit offcourse.
The way you are trying to do this is slightly wrong. You will need to use EXECUTE in order to achieve this.
CREATE PROCEDURE [dbo].[sp_getUserRoles](#pGroupIDs nvarchar(50))
As
BEGIN
EXECUTE (N'SELECT * FROM CheckList_Groups Where id in (' + #pGroupIDs + ')';
END
DECLARE #TagId NVARCHAR(100) = '43,81'
SELECT * FROM TABLE WHERE TagId IN (SELECT TRIM(VALUE) FROM STRING_SPLIT( #TagId , ',' ) )
USE STRING_SPLIT FUNCTION FOR THIS
You need to use SP_executesql to achieve this functionllity
CREATE Procedure [dbo].[sp_getUserRoles](
#pGroupIDs varchar(50)
)
As
BEGIN
EXECUTE sp_executesql
N'SELECT * FROM CheckList_Groups Where id in (#pGroupIDs)',
N'#level varchar(50)',
#level = #pGroupIDs;
End
The IN clause can't take a bound parameter like that. What it's being given when the query is actually created is SELECT * FROM CheckList_Groups Where id in ('1,2,3,4'). Essentially the IN clause is being passed a single string.
First create function -
Just run this code
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[CSVToTable] (#InStr VARCHAR(MAX))
RETURNS #TempTab TABLE
(id int not null)
AS
BEGIN
;-- Ensure input ends with comma
SET #InStr = REPLACE(#InStr + ',', ',,', ',')
DECLARE #SP INT
DECLARE #VALUE VARCHAR(1000)
WHILE PATINDEX('%,%', #INSTR ) <> 0
BEGIN
SELECT #SP = PATINDEX('%,%',#INSTR)
SELECT #VALUE = LEFT(#INSTR , #SP - 1)
SELECT #INSTR = STUFF(#INSTR, 1, #SP, '')
INSERT INTO #TempTab(id) VALUES (#VALUE)
END
RETURN
END
GO
Then -
Use function in bracket with select statment -
DECLARE #LIST VARCHAR(200)
SET #LIST = '1,3'
SELECT Id, Descr FROM CSVDemo WHERE Id IN (SELECT * FROM dbo.CSVToTable(#LIST))

Resources