Can someone help me figure out why this is not working.
Here's the SP:
CREATE PROCEDURE sGetPeriods #PeriodTypeID INT, #ParentPeriodID INT
AS
BEGIN
SET NOCOUNT ON
SELECT PeriodID, Period
FROM Periods
WHERE CASE WHEN #PeriodTypeID IS NULL THEN 1
WHEN #PeriodTypeID = PeriodTypeID THEN 1
ELSE 0
END = 1
AND CASE WHEN #ParentPeriodID IS NULL THEN 1
WHEN #ParentPeriodID = ParentPeriodID THEN 1
ELSE 0
END = 1
ORDER BY Period
END
GO
Here's the C# code that calls the SP:
private DataTable CmdExecuteToDataTable(SqlCommand objSQLCmd)
{
DataTable dtReturn = new DataTable();
using (SqlConnection objSQLConn = new SqlConnection(c_szSQLConnectionString))
{
objSQLConn.Open();
objSQLCmd.Connection = objSQLConn;
if (bLog)
{
//WriteLog("Connection: " + objSQLConn.ConnectionString);
WriteLog("CmdExecuteToDataTable(" + objSQLCmd.CommandText + ")");
for (int zz = 0; zz < objSQLCmd.Parameters.Count; zz++)
{
WriteLog(objSQLCmd.Parameters[zz].ParameterName + ": " + objSQLCmd.Parameters[zz].Value.ToString());
}
}
SqlDataReader _r = objSQLCmd.ExecuteReader();
if (_r.HasRows)
{
DataReaderAdapter _dra = new DataReaderAdapter();
_dra.FillFromReader(dtReturn, _r);
}
_r.Close();
}
if (bLog)
{
WriteLog("\t" + "Returned: " + dtReturn.Rows.Count.ToString() + " rows.");
WriteLog(("-").PadRight(80, '-'));
}
return dtReturn;
}
And, here's the code that calls the above method:
public DataTable GetPeriods(int iPeriodTypeID, int iParentPeriodID)
{
SqlCommand objSQLCmd = new SqlCommand("sGetPeriods");
objSQLCmd.Parameters.Clear();
if (iPeriodTypeID != 0)
objSQLCmd.Parameters.Add(new SqlParameter("#PeriodTypeID", iPeriodTypeID));
if (iParentPeriodID != 0)
objSQLCmd.Parameters.Add(new SqlParameter("#ParentPeriodID", iParentPeriodID));
return CmdExecuteToDataTable(objSQLCmd);
}
Finally, here's the page code that calls the method above:
int iPeriodTypeID = 1;
int iParentPeriodID = 1;
DataTable dtPeriods = clsDataLayer.GetPeriods(iPeriodTypeID, iParentPeriodID);
When the page loads, I get
Procedure or function 'sGetPeriods' expects parameter '#PeriodTypeID', which was not supplied.
Yet, the parameter IS supplied as verified by the LOG file entry:
8/19/2011 8:44:16 AM: CmdExecuteToDataTable(sGetPeriods)
8/19/2011 8:44:16 AM: #PeriodTypeID: 1
8/19/2011 8:44:16 AM: #ParentPeriodID: 1
Somehow, the stored procedure is not getting the values passed with the SQL Command object.
Any ideas?
FYI, when I defined the SP Like this:
CREATE PROCEDURE sGetPeriods #PeriodTypeID INT = NULL, #ParentPeriodID INT = NULL
the Procedure executes but returns ALL rows as if it had not received any parameters.
I tried wrapping the code within a using(sqlcommand sqlcmd = objSLQCmd) but that did not help.
Thanks for any pointers,
John
Try setting the CommandType of the SqlCommand to StoredProcedure.
At the moment, it interpreting it as a textual query (literally sGetPeriods). For a text query, you have to include the appropriate parameters in the text of the query, which you're not doing.
It's unfortunate that, if you give SQL a query batch that starts with a stored procedure name, it treats it as if an exec is present before that. It would have been a far more obvious error message if this wasn't so.
Related
I am using Oracle 12c as a database, C# Web Application. I am trying to execute an Oracle query from C# and load the data to the data table. I am getting an error like ORA-00933: SQL command not properly ended. I ran the same query in Toad and was getting the same error first time, but if I ran the same query again in the toad, the data is returning results. I am not sure, what is the syntax issue.
I have tried the below code:
using (var cmd = new OracleCommand {Connection = cn})
{
var selectStatement = "select * from tablename OFFSET #Offset ROWS FETCH NEXT 10000 ROWS ONLY;";
cn.Open();
cmd.CommandText = selectStatement;
cmd.Parameters.Add("#Offset", OracleDbType.Int64);
for (var index = 0; index < totalRecords; index++)
{
if (index % 10000 == 0)
{
cmd.Parameters["#Offset"].Value = index;
var dt = new DataTable()
{
TableName = tblName+"_"+index};
dt.Load(cmd.ExecuteReader());
dataTables.Add(dt);
tableIndex += 1;
}
}
}
}
I am trying to fetch the results in a paged manner. The error is shown in line cmd.ExecuteReader. How to fix this?
Update 1: Two solution which worked for this issue.
var selectStatement = "Select * from tableName OFFSET :Offset ROWS FETCH NEXT 10000 ROWS ONLY";
cmd1.CommandText = selectStatement;
var numParam = new OracleParameter();
numParam.ParameterName = "Offset";
numParam.OracleDbType = OracleDbType.Int32;
numParam.Direction = ParameterDirection.Input;
numParam.Value = offsetvalue;
cmd1.Parameters.Add(numParam);
I have removed the semi-colon from the query and also used the parameter as :Offset , rather than #Offset
Thanks
I need to enter some value in the textbox end save it to the database.
But if there is a duplicate value then the value must not be saved.
Basically, string lvl is successfully passed to the WebMethod from front-end via ajax.
Procedure getDuplicate is a simple select that checks if there is a value of lvl is already stored in the database. And InsertObject procedure inserts the value in the database.
If the value(lvl) exists then the ID of that value is return and stored in the Count integer.
The problem is if Count is returned with id number then if statement works,
and if there is no value in the database Count just does not receive any values and the procedure fails and goes straight to the catch part of the code.
I think there's a problem with the returning type from a database when there is no value in it. It is not INT or something.
Can anyone help, please?
[WebMethod(EnableSession = true)]
public static void GetCollection(string lvl)
{
string conn = ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;
using (SqlConnection connection = new SqlConnection(conn))
try
{
connection.Open();
SqlCommand cmdCount = new SqlCommand("getDuplicate", connection);
cmdCount.CommandType = CommandType.StoredProcedure;
cmdCount.Parameters.AddWithValue("#ObjekatName", lvl);
int count = (int)cmdCount.ExecuteScalar();
if (count > 0)
{
}
else
{
SqlCommand cmdProc = new SqlCommand("InsertObjekat", connection);
cmdProc.CommandType = CommandType.StoredProcedure;
cmdProc.Parameters.AddWithValue("#ObjekatName", lvl);
cmdProc.ExecuteNonQuery();
//strMsg = "Saved successfully.";
}
}
catch
{
}
finally
{
connection.Close();
}
return;
getDuplicate procedure
ALTER PROCEDURE [dbo].[GetDuplicate]
#ObjekatName nvarchar(20)
AS
BEGIN
SET NOCOUNT ON
SELECT TOP 1000 [ObjekatID]
,[ObjekatName]
FROM [MyApp].[dbo].[Objekat]
WHERE ObjekatName = #ObjekatName
END
Please change your GetDuplicate proc as below. It will always return a value.
CREATE PROCEDURE [dbo].[GetDuplicate]
#name nvarchar(20)
AS
BEGIN
DECLARE #duplicateCount int
SELECT #duplicateCount=count(*) FROM [dbo].[employee] WHERE name = #name
RETURN #duplicateCount
END
Looking at the example given here:
https://stackoverflow.com/a/452934
I understand that I will need to iterate through a loop and append value clauses, but what I am missing is how to amend the query to return all the ID's for the newly created records and retrieve them in C#?
For Example my current code can be seen below, I would like to change it to insert multiple rows in one query and retrieve the newly created Id's as a List of integers ideally.
in_new_id = -1;
String query = "INSERT INTO " + DB_Base.DBTable_Customer_Order_Table + "(" + DB_Base.DBTable_Customer_Order_Table_Customer_ID + "," + DB_Base.DBTable_Customer_Order_Table_ProductId+")";
query += " OUTPUT INSERTED." + DB_Base.DBTable_Customer_Order_Table_ID;
query += " VALUES ( #customerId, #productId);";
using (SqlConnection conn = new SqlConnection(GeneralConfig.DB_STR()))
{
SqlCommand sql_command = new SqlCommand(query, conn);
sql_command.Parameters.AddWithValue("#customerId", data_obj.customerId);
sql_command.Parameters.AddWithValue("#productId", data_obj.productId);
if (!String.IsNullOrEmpty(query) && sql_command != null && conn != null)
{
sql_command.Connection.Open();
if (sql_command.Connection.State == System.Data.ConnectionState.Open)
{
object out_new_id = sql_command.ExecuteScalar();
if (out_new_id != null)
{
in_new_id = (int)out_new_id;
}
sql_command.Connection.Close();
return ENUM_DB_Status.DB_SUCCESS;
}
else
{
in_new_id = -1;
return ENUM_DB_Status.DB_CONNECTION_COULD_NOT_OPEN;
}
}
}
return ENUM_DB_Status.DB_FAIL;
Use this:
List<int> ids = new List<int>();
using (SqlCommand command = new SqlCommand(#"declare #T TABLE(Id int)
INSERT INTO YourTableName(YourTableColumnNames)
OUTPUT Inserted.Id into #T VALUES
(YourValues1),
(YourValues2),
(YourValues3),
(etc...) select Id from #T ", con))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
int id = int.Parse(reader[0].ToString());
ids.Add(id);
}
}
}
Warning!!! This will work only if you're using SQLServer 2008 R2 or higher.
Edit: As Damien said in the comments : "There is no guarantee that the order in which the changes are applied to the table and the order in which the rows are inserted into the output table or table variable will correspond."
in C# project , I have made a datagridview in my form that has some columns.column[0]& column[1] names are fix (day and date) and the other column names are variable and will change by user.these columns have time period thatsis shown with starting and finishing time.
such as from 6 am to 14 pm is shown as 6_14 as columns name.we have a listbox that has variable number of items(counter "i").
///sqlite doesn't accept columns name that start and finish with Numbers.I added word "f" to start and end of each
///column name
string data_str = "";
string data_str2="";
for (int i = 0; i < listBox1.Items.Count;i++ )
{
string temp = "f"+ listBox1.Items[i].ToString()+"f";
data_str = data_str + temp +",";
string temp2 = "#"+listBox1.Items[i].ToString()+",";
data_str2=data_str2+temp2;
}
data_str=data_str.TrimEnd(',');
data_str2=data_str2.TrimEnd(',');
in first step,I made two columns "day" & "date" in data table in my database and imported my data to it successfully.(It works)
string Q_insert = "insert into " + table_name + " (day,date) values (#day,#date)";
SQLiteConnection connect = new SQLiteConnection(connection_string);
SQLiteCommand insert_cmd = new SQLiteCommand(Q_insert, connect);
foreach (DataGridViewRow row in shift_datagrid.Rows)
{
insert_cmd.Parameters.AddWithValue("#day", row.Cells[0].Value.ToString().Trim());
insert_cmd.Parameters.AddWithValue("#date", row.Cells[1].Value.ToString().Trim());
connect.Open();
insert_cmd.ExecuteNonQuery();
connect.Close();
}
in second step,I need to import user data from datagridview to data table but the error takes place.(it doesn't work)
int col_cnt = listBox1.Items.Count;
Q_insert = "insert into " + table_name + " (" + data_str + ") values (" + data_str2 + ")";
connect = new SQLiteConnection(connection_string);
insert_cmd = new SQLiteCommand(Q_insert, connect);
foreach (DataGridViewRow row in shift_datagrid.Rows)
{
string temp1 = "";
for (int i = 0; i < col_cnt; i++)
{
temp1 = "\"#" + listBox1.Items[i].ToString() +"\"";
insert_cmd.Parameters.AddWithValue(temp1, row.Cells[i + 2].Value.ToString().Trim());
}
connect.Open();
insert_cmd.ExecuteNonQuery();
connect.Close();
}
unfortunately, this error occurs:
unknown Error : Insufficient parameters supplied to the command
I googled this error and checked solution ways for same problems but they were not useful for my problem and they couldn't help me anyway.
this is the example of output command strings that insert to data to database (two steps):
1. Insert into [table_name] (day,date) values (#day,#date) -------------->(it works)
2. Insert into [table_name] (f6_14f,f14_22f,f22_6f) values (#6_14,#14_22,#22_6) ------->(it doesn't work)
please help me
thanks
The following may be causing the error:
temp1 = "\"#" + listBox1.Items[i].ToString() +"\"";
insert_cmd.Parameters.AddWithValue(temp1, row.Cells[i + 2].Value.ToString().Trim());
Syntax requires that you don't construct the # as part of the variable value.# is not data. Use it as part of the variable name as you did before like this:
insert_cmd.Parameters.AddWithValue("#Col1",listBox1.Items[i+2].Value.ToString().Trim());
Where #Col1 is a column name of your table.
I don't think you can build the parameter name in a for loop, if so, you have to list the insert statements with each column name parameter prefixed with # as in the above example/code.
I have searched and tried different things for the past week or so and my problem is possibly to specific to find an answer through google.
If I execute this query in SQL Server Management Studio and replace the parameter #zoekterm with '%something%', it works fine and returns the result that I want. But when I call the same procedure from C# it returns nothing.
Is this a bug or am I just that stupid?
Here's code of stored procedure and function in C#, (I know I should have used switch case...)
Stored procedure:
-- =============================================
-- Author: Daan
-- Create date:
-- Description:
-- =============================================
ALTER PROCEDURE [dbo].[quick_bedrijf]
-- Add the parameters for the stored procedure here
#zoekterm varchar(100) = 0
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 bedrijf.bedrijf_nr, bedrijf.zoeknaam, bedrijf.plaats
FROM bedrijf
WHERE zoeknaam LIKE #zoekterm AND NIETactief = 0
ORDER BY bedrijf.zoeknaam, bedrijf.plaats
END
C#:
private void snel_zoek2()
{
listView1.Items.Clear();
con.Open();
if (type == 1)
{
command1 = new SqlCommand("quick_project", con);
colnum = 5;
}
else if (type == 2)
{
command1 = new SqlCommand("quick_bedrijf", con);
colnum = 3;
}
else if (type == 3)
{
command1 = new SqlCommand("quick_persoon", con);
colnum = 4;
}
command1.CommandType = CommandType.StoredProcedure;
SqlParameter zoekterm = command1.Parameters.Add("#zoekterm", SqlDbType.VarChar, 100);
zoekterm.Direction = ParameterDirection.Input;
//command1.Parameters.Add(new SqlParameter("#zoekterm", SqlDbType.VarChar)).Value = " '%zee%'";// + textBox2.Text.ToString()+
zoekterm.Value = "'%"+textBox2.Text.ToString()+"%'";
// MessageBox.Show(zoekterm.Value.ToString());
SqlDataAdapter adapt = new SqlDataAdapter();
DataTable dt = new DataTable();
adapt.SelectCommand = command1;
adapt.Fill(dt);
dataGridView1.BindingContext = new BindingContext();
dataGridView1.DataSource = dt;
con.Close();
}
You don't put the quotes into the parameter (those are to signify a literal); it should be:
zoekterm.Value = "%"+textBox2.Text+"%";
It is failing currently because if the text is "abc", it is looking for a string that starts and ends with a single quote and includes "abc". In SQL terms, you were asking it for:
LIKE '''%abc%'''