Error calling SQL Server stored procedure from C# code - c#

I have a stored procedure to create table in a SQL Server database. I need to call this stored procedure from C#. I get an exception
Incorrect Syntax near #TABLENAME
How do I fix this? I have the table name and column list from a xml file.
Stored procedure:
CREATE PROCEDURE PROC_CREATE_SFCOM_TABLE2
#TABLENAME VARCHAR(4000) ,
#COLUMNLIST VARCHAR(4000) ,
#ERRORMSG VARCHAR(4000) OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE #EXEC_IMMEDIATE_VAR VARCHAR (4000)
SELECT #EXEC_IMMEDIATE_VAR = 'CREATE TABLE #TABLENAME#COLUMNLIST '
EXECUTE (#EXEC_IMMEDIATE_VAR)
END
GO
C# Code:
using (SqlConnection conn = new SqlConnection(connstring)
{
using (SqlCommand cmd = new SqlCommand("dbo.PROC_CREATE_SFCOM_TABLE2",conn))
{
cmd.CommandType = CommandType.StoredProcedure;
createScript = "("+columnScript+")";
if (tableTableSpace != null)
{
if (tableTableSpace != "" || tableTableSpace != string.Empty)
{
createScript += "TABLESPACE " + tableTableSpace;
}
}
SqlParameter parameter = new SqlParameter("#TableName",SqlDbType.NVarChar);
parameter.Direction = ParameterDirection.Input;
parameter.Value = tableName;
cmd.Parameters.Add(parameter);
SqlParameter parameter2 = new SqlParameter("#COLUMNLIST",SqlDbType.NVarChar);
parameter2.Direction = ParameterDirection.Input;
parameter2.Value = createScript;
cmd.Parameters.Add(parameter2);
SqlParameter parameter3 = new SqlParameter("#ErrorMsg", SqlDbType.NVarChar);
parameter3.Direction = ParameterDirection.Output;
parameter3.Size = 4000;
cmd.Parameters.Add(parameter3);
conn.Open();
cmd.ExecuteNonQuery();
string errorMsg = parameter3.Value.ToString();
if (errorMsg != string.Empty)
LogInfo("Error: " + errorMsg);

You can't parameterize your table or column names. You can only parameterize your values. Only way is to execute dynamic sql.
But you should have a very strong validation for that if you want to create a table dynamic. Create a white list for that for example.
Before you do that, read: The Curse and Blessings of Dynamic SQL

You didn't create the dynamic SQL string correctly. Change it to this...
CREATE PROCEDURE PROC_CREATE_SFCOM_TABLE2
#TABLENAME VARCHAR(4000) ,
#COLUMNLIST VARCHAR(4000) ,
#ERRORMSG VARCHAR(4000) OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE #EXEC_IMMEDIATE_VAR VARCHAR (4000)
SELECT #EXEC_IMMEDIATE_VAR = 'CREATE TABLE [' + #TABLENAME + '] ' + #COLUMNLIST
EXECUTE (#EXEC_IMMEDIATE_VAR)
END
GO
However, please note that this is a very dangerous thing to do. #COLUMNLIST could contain anything, including other SQL commands, which could be used for a SQL injection attack

Related

Getting null Value when executing a SQL Server stored procedure in C#

I am executing a SQL Server stored procedure in C#, but both my output parameters are returned blank. But when I run this stored procedure directly in SSMS, then I get values for both parameters. I used same input order no.
Can anyone tell me what's wrong in my code? Thank you
using (SqlConnection con = new SqlConnection(CS))
{
SqlCommand cmd = new SqlCommand("wt_find_open_pick_ticket_count", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#input_order_no", order_no);
cmd.Parameters.Add("#status", SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.Parameters.Add("#results", SqlDbType.VarChar, 1000).Direction = ParameterDirection.Output;
con.Open();
cmd.ExecuteNonQuery();
MessageBox.Show(cmd.Parameters["#status"].Value.ToString());
MessageBox.Show(cmd.Parameters["#results"].Value.ToString());
}
ALTER procedure wt_find_open_pick_ticket_count
#input_order_no varchar(20),
#results varchar(1000) OUTPUT,
#status int OUTPUT
AS
SELECT
status =
CASE
WHEN COUNT(oe_pick_ticket.pick_ticket_no)>0 THEN 0
ELSE 1
END,
results =
CASE
WHEN COUNT(oe_pick_ticket.pick_ticket_no)> 0 THEN 'Message'
ELSE ''
END
FROM oe_pick_ticket with (nolock)
WHERE
oe_pick_ticket.order_no = #input_order_no
AND oe_pick_ticket.invoice_no IS NULL
AND oe_pick_ticket.delete_flag = 'N'
AND oe_pick_ticket.print_date > '2014-01-01'
GROUP BY oe_pick_ticket.order_no
This stored procedure returns a resultset. It does not return output parameters. In order to return output paramters, SP has to change to something like:
select
#paramout1 = val1,
#paramout2 = val2
Notice "#" that is preceding parameter names.

data insert using input output stored procedure

I am creating a web application using ASP.net C#. I have a booking form and I need to insert data into a table using a Stored Procedure. The table has several columns, out of which second column is a computed column. The Stored Procedure is set up to insert the data and fetch the value from the second column after insert. Below is the code for Stored Procedure:
Create Procedure sp_InsertCashPooja
#FirstName varchar(100),
#LastName varchar(100),
#TelNo bigint,
#Star char(50),
#Rasi char(50),
#Gothram char(50),
#PDMID int,
#PayMode bit,
#PujaName char(50),
#DonateAmt decimal(19,2),
#RcptNo varchar(25) output
as
Begin
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION
if #PujaName != 'DONATION'
Begin
INSERT INTO PoojaDetails (FirstName, LastName, TelNo, Star, Rasi, Gothram, PoojaDietyMasterID, PayMode) values (#FirstName,#LastName,#TelNo,#Star,#Rasi,#Gothram,#PDMID,#PayMode)
End
if #PujaName = 'DONATION'
Begin
DECLARE #isDonate int = 0;
INSERT INTO PoojaDetails (FirstName, LastName, TelNo, Star, Rasi, Gothram, PoojaDietyMasterID, PayMode, isDonate, DonateAmount) values (#FirstName,#LastName,#TelNo,#Star,#Rasi,#Gothram,#PDMID,#PayMode, #isDonate, #DonateAmt)
End
Select #RcptNo = max(ReceiptNo) from PoojaDetails
Return #RcptNo
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF (##TRANCOUNT > 0)
ROLLBACK TRANSACTION
END CATCH
SET NOCOUNT OFF;
End
I would like to insert data on the click of a button: I was able to figure out the below code....
protected void btnSave_Click(object sender, EventArgs e)
{
frmFirstName = txtFirstName.Text.Trim().ToUpper();
frmLastName = txtLastName.Text.Trim().ToUpper();
frmPhoneNo = Convert.ToInt32(txtPhoneNo.Text.Trim());
frmNakshatra = Convert.ToString(cmbNakshatra.SelectedItem).Trim();
frmRasi = Convert.ToString(cmbRasi.SelectedItem).Trim();
frmGothram = Convert.ToString(cmbGothram.SelectedItem).Trim();
frmPujaName = Convert.ToString(cmbPujaName.SelectedItem).Trim();
using (SqlConnection connection = new SqlConnection())
{
if (frmPayMode == "Cash")
{
if (frmPujaName == "DONATION")
{
SqlDataAdapter CashAdapter = new SqlDataAdapter();
CashAdapter.InsertCommand = new SqlCommand("sp_InsertCashPooja", connection);
CashAdapter.InsertCommand.CommandType = CommandType.StoredProcedure;
Please help.... I want to capture the returning RcptNo and later intend to call another ASPX page and pass the value using a Query String.
Thanks
Use simple SqlCommand for calling your SP
connection.Open();
var cmd = new SqlCommand("sp_InsertCashPooja", connection);
cmd.Parameters.AddWithValue("FirstName", frmFirstName);
// Add all the others parameters in same way
var id = (int)cmd.ExecuteScalar();
connection.Close();
Change the return variable to:
Select #RcptNo = SCOPE_IDENTITY()
It will return the identity number created for the inserted record within this procedure.
use sql parameter..
connection = ConfigurationManager.AppSettings["mycon"];
SqlParameter[] para = new SqlParameter[2];
para[0] = new SqlParameter("#stored procedure column name", string name);
para[1] = new SqlParameter("#stored procedure column name", string name);

C# dynamic query builder with SQL variables configurable

Am developing a Prototype where in i can access the SQL server dynamically.Table names and column names should be configurable at run time.
Eg: If am selecting a table or inserting records i should pass those values to a Prototype Class with table name,column name and parameters. and the class should take care of the rest.
Am trying to build that class.
Advice on the recommended steps to start.
Thanks
DECLARE #ColName nvarchar(4000)
DECLARE #TableName nvarchar(4000)
DECLARE #ColName2 nvarchar(4000)
DECLARE #Parameter nvarchar(4000)
set #TableName='tblTest'
set #ColName='ID'
set #ColName2='colValue'
set #Parameter=1
DECLARE #sql nvarchar(4000)
SET #sql = ' SELECT '+#ColName+' from ' + #TableName+ ' where '+#ColName2+'='+#Parameter
exec(#sql)
this is what i am doing. you can pass the above given parameters to a stored procedure and that will do a trick
Maybe That is Useful ...
//Method
public void insertCheque()
{
try {
SqlParameter[] param = new SqlParameter[5];
param[0] = new SqlParameter("#IdBankChequeBook", SqlDbType.Int);
param[1] = new SqlParameter("#IdBankChequeType", SqlDbType.Int);
param[2] = new SqlParameter("#IdBankChequeStatus", SqlDbType.Int);
param[3] = new SqlParameter("#TransType",SqlDbType.Int);
param[4] = new SqlParameter("#ClientID",SqlDbType.Int);
//send sql parameter to stored procedure
SqlHelper.ExecuteNonQuery(Connecting.LCM, CommandType.StoredProcedure, "InsertBankCheque",param);
}
catch (Exception ex)
{
}
}
//Stored Procedure Related
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER PROCEDURE [dbo].[InsertBankCheque]
#IdBankChequeBook int ,
#IdBankChequeType int ,
#IdBankChequeStatus int ,
#TransType int ,
#ClientID int ,
As
Insert into BankCheque
(
IdBankChequeBook,
IdBankChequeType,
IdBankChequeStatus,
TransType ,
ClientID )
values
(
#IdBankChequeBook,
#IdBankChequeType,
#IdBankChequeStatus,
#TransType,
#ClientID )

Output parameter issue in sql server and c#

Why if I have this stored procedure created with an output parameter, I'm getting the following error:
sp_DTS_InsertLSRBatch expects parameter #ErrorMsg which was not
supplied
Stored procedure code:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER PROCEDURE [dbo].[sp_DTS_InsertLSRBatch]
#LSRNbr varchar(10),
#BatchNbr varchar(10),
#ErrorMsg varchar(20) output
AS
BEGIN
SET NOCOUNT ON;
if not exists(select *
from tblDTS_LSRBatch (nolock)
where LSRNbr=#LSRNbr and BatchNbr=#BatchNbr)
begin
-- check if BatchNbr exists under another LSR
-- if not add (LSR, BatchNbr) else error
if not exists(select *
from tblDTS_LSRBatch (nolock)
where BatchNbr=#BatchNbr)
insert into tblDTS_LSRBatch (LSRNbr,BatchNbr) values (#LSRNbr, #BatchNbr)
else
set #ErrorMsg = 'Batch dif LSR'
end
END
C# code:
SqlConnection conn = new SqlConnection(ConnStr);
try
{
conn.Open();
for (int i = 0; i <= lbxBatch.Items.Count - 1; i++)
{
SqlCommand cmd = new SqlCommand("sp_DTS_InsertLSRBatch", conn);
cmd.Parameters.Add(new SqlParameter("#LSRNbr", txtLSR.Text));
cmd.Parameters.Add(new SqlParameter("#BatchNbr", lbxBatch.Items[i].ToString()));
//Output parameter "ErrorMsg"
SqlParameter pErrorMsg = new SqlParameter("#ErrorMsg", SqlDbType.VarChar, 20);
pErrorMsg.Direction = ParameterDirection.Output;
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery(); <--- ERROR
In your code you haven't added the pErrorMsg parameter. Add this line:
cmd.Parameters.Add(pErrorMsg);
Moreover, in your Stored Procedure, you must set #ErrorMsg sql output variable to an appropriate value like an empty string or double double-quotes ("") in the if condition parts of your SP code,as a good coding practice.
You're creating the pErrorMsg parameter, but where are you adding it to your command?

Stored Procedure Default Value

I'm a newbie when it comes to SQL. When creating a stored procedure with parameters as such:
#executed bit,
#failure bit,
#success bit,
#testID int,
#time float = 0,
#name varchar(200) = '',
#description varchar(200) = '',
#executionDateTime nvarchar(max) = '',
#message nvarchar(max) = ''
This is the correct form for default values in T-SQL? I have tried to use NULL instead of ''.
When I attempted to execute this procedure through C# I get an error referring to the fact that description is expected but not provided. When calling it like this:
cmd.Parameters["#description"].Value = result.Description;
result.Description is null. Should this not default to NULL (well '' in my case right now) in SQL?
Here's the calling command:
cmd.CommandText = "EXEC [dbo].insert_test_result #executed,
#failure, #success, #testID, #time, #name,
#description, #executionDateTime, #message;";
...
cmd.Parameters.Add("#description", SqlDbType.VarChar);
cmd.Parameters.Add("#executionDateTime", SqlDbType.VarChar);
cmd.Parameters.Add("#message", SqlDbType.VarChar);
cmd.Parameters["#name"].Value = result.Name;
cmd.Parameters["#description"].Value = result.Description;
...
try
{
connection.Open();
cmd.ExecuteNonQuery();
}
...
finally
{
connection.Close();
}
A better approach would be to change the CommandText to just the name of the SP, and the CommandType to StoredProcedure - then the parameters will work much more cleanly:
cmd.CommandText = "insert_test_result";
cmd.CommandType = CommandType.StoredProcedure;
This also allows simpler passing by name, rather than position.
In general, ADO.NET wants DBNull.Value, not null. I just use a handy method that loops over my args and replaces any nulls with DBNull.Value - as simple as (wrapped):
foreach (IDataParameter param in command.Parameters)
{
if (param.Value == null) param.Value = DBNull.Value;
}
However! Specifying a value with null is different to letting it assume the default value. If you want it to use the default, don't include the parameter in the command.
If you aren't using named parameters, MSSQL takes the parameters in the order received (by index). I think there's an option for this on the cmd object.
so your SQL should be more like
EXEC [dbo].insert_test_result
#executed = #executed,
#failure = #failure,
#success = #success,
#testID = #testID,
#time = #time,
#name = #name,
#description = #description,
#executionDateTime = #executionDateTime,
#message = #message;
cmd.CommandText = "insert_test_result";
cmd.Parameters.Add(new SQLParameter("#description", result.Description));
cmd.Parameters.Add(new SQLParameter("#message", result.Message));
try
{
connection.Open();
cmd.ExecuteNonQuery();
}
finally
{
connection.Close();
}

Categories