Query with parameters in C# (using SQL Server) - c#

I have a problem with query in C#.
I have this part of code :
string query1 = #"
SELECT TOP #howManyRows * FROM
(
SELECT
PRODUCTCODE_.ID_ AS PRODUCTCODE_ID_,
PRODUCTCODE_.CATEGORY_ AS CATEGORY_,
PRODUCTCODE_.DESCRIPTION_ AS DESCRIPTION_,
PRODUCTCODE_.MANUFACTURER_ AS MANUFACTURER_,
PRODUCTLINE_.CREATION_DATE_ AS CREATION_DATE_,
ROW_NUMBER() OVER (ORDER BY PRODUCTCODE_.CATEGORY_) AS ROWNUMBER_,
TOTALROWS_ = COUNT(*) OVER()
FROM
PRODUCTCODE_
INNER JOIN
PRODUCTLINE_ ON PRODUCTLINE_.ID_ = PRODUCTCODE_.PRODUCTLINE_ID_
) _tmpList
WHERE
ROWNUMBER_ >= #startingWith
ORDER BY CATEGORY_
";
SqlParameter param1 = new SqlParameter();
param1.ParameterName = "#howManyRows";
param1.Value = resultPerPage; //`resultPerPage` is an integer function parameter
SqlParameter param2 = new SqlParameter();
param2.ParameterName = "#startingWith";
param2.Value = startsWith; //`startWith` is an integer function parameter
SqlCommand cmd = new SqlCommand( query1, connect );
cmd.Parameters.Add( param1 );
cmd.Parameters.Add( param2 );
When debug arrived to SqlDataReader reader = cmd.ExecuteReader(); then the exception is thrown:
Incorrect syntax near #howManyRows ...
Why ? I defined and added howManyRows with Parameters property.
Where is my mistakes ?

Change your top query syntax from
SELECT TOP #howManyRows * FROM
to
SELECT TOP (#howManyRows) * FROM

Try wrapping the parameter specified next to TOP in parentheses, like so:
SELECT TOP (#howManyRows) * FROM

You need parenthesis to parametrise TOP
SELECT TOP (#howManyRows) * FROM

This will work.
SELECT
PRODUCTCODE_.ID_ AS PRODUCTCODE_ID_,
PRODUCTCODE_.CATEGORY_ AS CATEGORY_,
PRODUCTCODE_.DESCRIPTION_ AS DESCRIPTION_,
PRODUCTCODE_.MANUFACTURER_ AS MANUFACTURER_,
PRODUCTLINE_.CREATION_DATE_ AS CREATION_DATE_,
ROW_NUMBER() OVER (ORDER BY PRODUCTCODE_.CATEGORY_) AS ROWNUMBER_,
TOTALROWS_ = COUNT(*) OVER()
FROM
PRODUCTCODE_
INNER JOIN
PRODUCTLINE_ ON PRODUCTLINE_.ID_ = PRODUCTCODE_.PRODUCTLINE_ID_
) _tmpList
WHERE
ROWNUMBER_ between #startingWith and (#startingWith + #howManyRows)
ORDER BY CATEGORY_

You need to add a couple of parenthesis to make it work.
SELECT TOP (#howManyRows) * FROM

Use SELECT TOP(#howManyRows) syntax

You can do
SELECT TOP (#howManyRows) * FROM
But this really depends on the Database Server you are using. For example, this is only supported from MSSQL Server 2005 upwards
If this does not work you can do the following...
You can include this into your query string. But this can result in Sql Injection if you don't check the value of your variable.
Sample
int top = 10;
Int32.TryParse(howManyRows.ToString(), out top);
string query1 = "SELECT TOP " + top.ToString() + #" * FROM
(
SELECT
PRODUCTCODE_.ID_ AS PRODUCTCODE_ID_,
PRODUCTCODE_.CATEGORY_ AS CATEGORY_,
PRODUCTCODE_.DESCRIPTION_ AS DESCRIPTION_,
PRODUCTCODE_.MANUFACTURER_ AS MANUFACTURER_,
PRODUCTLINE_.CREATION_DATE_ AS CREATION_DATE_,
ROW_NUMBER() OVER (ORDER BY PRODUCTCODE_.CATEGORY_) AS ROWNUMBER_,
TOTALROWS_ = COUNT(*) OVER()
FROM
PRODUCTCODE_
INNER JOIN
PRODUCTLINE_ ON PRODUCTLINE_.ID_ = PRODUCTCODE_.PRODUCTLINE_ID_
) _tmpList
WHERE
ROWNUMBER_ >= #startingWith
ORDER BY CATEGORY_
";

Related

Pass a string parameter to command text with quotes

I'm trying to pass a parameter to the query but with quotes as a string value.
But I can seem to get it working.
What am I doing wrong here.
SqlConnection conn = new SqlConnection(SERP_FT_connection);
SqlCommand cmd = new SqlCommand("SELECT sp.* "
+ " FROM [serp_post] sp "
+ " LEFT JOIN [serp_m3_data] m3 ON m3.serp_post_id = sp.serp_post_id "
+ " WHERE sp.[serp_status_id]='CLEAR_DONE' AND sp.m3UpdateStatus <> '2' AND sp.process_type='POST' AND m3.EGTRCD = '40' AND m3.EPPYME = #paymentTerm ", conn);
cmd.CommandType = CommandType.Text;
conn.Open();
SqlParameter param = new SqlParameter();
param.ParameterName = "#paymentTerm";
param.Value = paymentTerm; // when debugged here it shows as "CH1"
cmd.Parameters.Add(param);
Query looks like this when debugged,
SELECT sp.* FROM [serp_post] sp LEFT JOIN [serp_m3_data] m3 ON m3.serp_post_id = sp.serp_post_id WHERE sp.[serp_status_id]='CLEAR_DONE' AND sp.m3UpdateStatus <> '2' AND sp.process_type='POST' AND m3.EGTRCD = '40' AND m3.EPPYME = #paymentTerm
Finally the query should look like this value passed with quotes
SELECT sp.* FROM [serp_post] sp LEFT JOIN [serp_m3_data] m3 ON m3.serp_post_id = sp.serp_post_id WHERE sp.[serp_status_id]='CLEAR_DONE' AND sp.m3UpdateStatus <> '2' AND sp.process_type='POST' AND m3.EGTRCD = '40' AND m3.EPPYME = 'CH1'
Try catch the parameterized query in the Profiler. Correct query will look something like
exec sp_executesql N' SET FMTONLY OFF; SET NO_BROWSETABLE ON;SELECT sp.* FROM [serp_post] sp LEFT JOIN [serp_m3_data] m3 ON m3.serp_post_id = sp.serp_post_id WHERE sp.[serp_status_id]='CLEAR_DONE' AND sp.m3UpdateStatus <> '2' AND sp.process_type='POST' AND m3.EGTRCD = '40' AND m3.EPPYME = #paymentTerm',N'#paymentTerm varchar(10)',#paymentTerm='CH1'
As Jon Skeet said, SQL parameters aren't inserted into the query.
Aside from the comments that actually present the PARAMETERS are automatically handled during the post and not LITERAL in the query as to prevent sql-injection.
As for the other answer about double-quotes, I have gotten into the habit of writing my sql in C# as sample below to help prevent accidental double-quotes in-use.
SqlCommand cmd = new SqlCommand( "", conn);
cmd.CommandText =
#"SELECT
sp.*
FROM
[serp_post] sp
LEFT JOIN [serp_m3_data] m3
ON m3.serp_post_id = sp.serp_post_id
WHERE
sp.[serp_status_id]='CLEAR_DONE'
AND sp.m3UpdateStatus <> '2'
AND sp.process_type='POST'
AND m3.EGTRCD = '40'
AND m3.EPPYME = #paymentTerm ";
Notice the fully readable query without scrolling or forgetting a close double-quote + on next line, etc... Again, just a style thing on building sql commands. The leading # means the entire text until it's closing other double-quote. Since SQL ignores enter keys in statements, they still work without issue and promote better readability.

Valid SQL Statement Returning 'Syntax Error" in Asp.NET

I'm making an ASP.Net web application, but it is returning a syntax error whenever I try to load the page.
My DB schema can be seen here http://sqlfiddle.com/#!2/739c4/7
Here is the SQL query:
SELECT
tblOrderTransactions.ordertransaction_orderid AS orderid,
tblProducts.product_name AS productname,
tblOrders.order_customer AS ordercustomer
FROM
tblProducts
LEFT JOIN tblOrderTransactions
ON tblProducts.product_id = tblOrderTransactions.ordertransaction_productid
LEFT JOIN tblOrders
ON tblOrderTransactions.ordertransaction_orderid = tblOrders.order_id
WHERE
(
(
(
tblOrderTransactions.ordertransaction_orderid
)
=3
)
) and (
(
(tblOrders.order_customer)
=3
)
)
The SQL works in sqlfiddle, and if I remove the part that says
LEFT JOIN tblOrders
ON tblOrderTransactions.ordertransaction_orderid = tblOrders.order_id
in my web application, the table loads. Adding this second INNER JOIN seems to be messing it up, but the same query works in sqlfiddle, so I believe the SQL is correct.
The error message I receive is
Syntax error (missing operator) in query expression 'tblProducts.product_id = tblOrderTransactions.ordertransaction_productid LEFT JOIN tblOrders ON tblOrderTransactions.ordertransaction_orderid = tblOrders.order_i'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.OleDb.OleDbException: Syntax error (missing operator) in query expression 'tblProducts.product_id = tblOrderTransactions.ordertransaction_productid LEFT JOIN tblOrders ON tblOrderTransactions.ordertransaction_orderid = tblOrders.order_i'.
C# Code inside the application:
string orderID = Request.QueryString["id"];
OleDbConnection conn = new OleDbConnection();
conn.ConnectionString = ConfigurationManager.ConnectionStrings["finalConnString"].ConnectionString;
string commText = #"SELECT tblOrderTransactions.ordertransaction_orderid AS orderid, tblProducts.product_name AS productname
FROM tblProducts
LEFT JOIN tblOrderTransactions
ON tblProducts.product_id = tblOrderTransactions.ordertransaction_productid
LEFT JOIN tblOrders
ON tblOrderTransactions.ordertransaction_orderid = tblOrders.order_id
WHERE (((tblOrderTransactions.ordertransaction_orderid)=?)) ";
conn.Open();
OleDbCommand comm = conn.CreateCommand();
comm.Connection = conn;
comm.CommandText = commText;
OleDbParameter param;
param = comm.CreateParameter();
param.DbType = DbType.Int32;
param.Direction = ParameterDirection.Input;
param.Value = Int32.Parse(orderID);
comm.Parameters.Add(param);
//param = comm.CreateParameter();
//param.DbType = DbType.Int32;
//param.Direction = ParameterDirection.Input;
//param.Value = Session["LoggedInId"];
//comm.Parameters.Add(param);
OleDbDataReader reader = comm.ExecuteReader();
if (reader.HasRows)
{
rptOrders.DataSource = reader;
rptOrders.DataBind();
lblOrderNumber.Text = orderID.ToString();
}
else
{
Response.Write("You are not authorized to view this order.");
}
//Free up the connection
conn.Close();
The SQL Statement must have the joins nested in parentheses because of Access specific syntax (Thank you #MattiVirkkunen for that knowledge).
The correct way to write this SQL statement is:
SELECT tblOrderTransactions.ordertransaction_orderid, tblProducts.product_name, tblOrders.order_customer
FROM tblProducts
INNER JOIN (tblOrders
INNER JOIN tblOrderTransactions
ON tblOrders.[order_id] = tblOrderTransactions.[ordertransaction_orderid])
ON tblProducts.[product_id] = tblOrderTransactions.[ordertransaction_productid]
WHERE (((tblOrderTransactions.ordertransaction_orderid)=3)) and (((tblOrders.order_customer)=3))
First, I would suggest working with aliases to keep your query a little shorter to read (and type) such as below.
SELECT
OT.ordertransaction_orderid AS orderid,
P.product_name AS productname,
O.order_customer AS ordercustomer
FROM
tblProducts P
LEFT JOIN tblOrderTransactions OT
ON P.product_id = OT.ordertransaction_productid
LEFT JOIN tblOrders
ON OT.ordertransaction_orderid = O.order_id
WHERE
OT.ordertransaction_orderid = 3
and O.order_customer = 3
Second, it does look completely legit and nothing glaring out as invalid. But error of loading the page MIGHT be due to no records being returned. You have your query with left-joins, but then throwing in your WHERE clause for both the "tblOrderTransactions" and "tblOrders" tables changes it to an INNER JOIN result.
So, your query looking for order ID = 3 and also the customer = 3, what if that was not the case, that order #3 was customer #1 which would result in NO RECORDS.
Getting back to now seeing your posted syntax, it looks unbalanced parens ((( )) that might be the issue.
And a final review.. Your "ID" from the query string. Is it properly doing an int.Parse() against it? I know on some instances of int.parse() I've done in the past, if the string started with a space vs actual number, int.Parse() would throw an error... Confirm the incoming values and did it really convert as you expected.

C# SqlCommand is not sending the right query with parameters

It's a pretty simple problem, but I can't find a solution (not even sure what question to google here).
Here is my code to create the command:
var targetStartDate = "October 2014";//ConfigurationManager.AppSettings["StartDateString"].ToString(CultureInfo.InvariantCulture);
var acceptedStatusCodes = 4;//ConfigurationManager.AppSettings["ImportStatusIds"].ToString(CultureInfo.InvariantCulture);
using (var connection = new SqlConnection(connString))
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = #"
SELECT
ai.FirstName,
ai.LastName,
ai.Email,
ai.SSN,
ai.Phone,
ai.Program,
r.FirstName + ' ' + r.LastName AS RepName,
d.Name AS StartDateName,
s.CvId AS CvSySchoolStatusId,
ai.CampusId as SyStudentId
FROM
dbo.aspnet_Users AS u LEFT OUTER JOIN
dbo.ApplicantInfo AS ai ON u.UserId = ai.UserId LEFT OUTER JOIN
dbo.AdmissionReps AS r ON ai.AdmissionsRepId = r.RepId LEFT OUTER JOIN
dbo.ProgramStartDate AS d ON ai.StartDateId = d.CvStartDateId LEFT OUTER JOIN
dbo.CvSySchoolStatus AS s ON ai.CvSySchoolStatusId = s.CvId
where d.Name = '#StartDate'
and CvSySchoolStatusId in (#Statuses)";
cmd.Parameters.AddWithValue("#StartDate", SqlDbType.VarChar).Value = (object) targetStartDate;
cmd.Parameters.AddWithValue("#Statuses", SqlDbType.Int).Value = (object) acceptedStatusCodes;
...
}
....
}
The reader sends the command fine, I can see it go through via SQL profiler:
exec sp_executesql N'
SELECT
ai.FirstName,
ai.LastName,
ai.Email,
ai.SSN,
ai.Phone,
ai.Program,
r.FirstName + '' '' + r.LastName AS RepName,
d.Name AS StartDateName,
s.CvId AS CvSySchoolStatusId,
ai.CampusId as SyStudentId
FROM
dbo.aspnet_Users AS u LEFT OUTER JOIN
dbo.ApplicantInfo AS ai ON u.UserId = ai.UserId LEFT OUTER JOIN
dbo.AdmissionReps AS r ON ai.AdmissionsRepId = r.RepId LEFT OUTER JOIN
dbo.ProgramStartDate AS d ON ai.StartDateId = d.CvStartDateId LEFT OUTER JOIN
dbo.CvSySchoolStatus AS s ON ai.CvSySchoolStatusId = s.CvId
where d.Name = ''#StartDate''
and CvSySchoolStatusId in (#Statuses)'
,N'#StartDate nvarchar(12),#Statuses int'
,#StartDate=N'October 2014'
,#Statuses=4
This query gives me 0 results, but if I take this exact query and just paste in the parameters and run just the query text, I get the expected results. Any idea where I am going wrong here?
You need to remove single quotes around your parameter in string query
this:
where d.Name = '#StartDate'
should be:
where d.Name = #StartDate
No single parameters.
Perhaps it's the extra single quotes around startdate. I think you might want to remove those single quotes and try again. Should look like:
...
where d.Name = #StartDate

Select more columns with MAX function in SQLCE

Need to find max value of id, and by this value I need to read value of others column. But it is influenced by another column type.
I used this sql command:
"SELECT * FROM Table WHERE id = (SELECT MAX(id) FROM Table WHERE type = 1)"
ID column is bigint type, and type is nchar. I tried use it with type = '1' too, but same problem.
Error is after "id = " section
Thanks for reply
EDIT:
SqlCeCommand com = new SqlCeCommand();
if (LocalType == '1') { com = new SqlCeCommand("SELECT req_id FROM Requisition WHERE id = (SELECT MAX(id) FROM Requisition WHERE type = 1)", con); }
else if (LocalType == '2') { com = new SqlCeCommand("SELECT req_id FROM Requisition WHERE id = (SELECT MAX(b.id) FROM Requisition AS b WHERE b.type <> 1)", con); }
using (com)
{
SqlCeDataReader reader = com.ExecuteReader();
}
The easiest way to do this is using top. If this is your real code, then you need to "escape" the word "table" because it is a reserved word:
select top 1 t.*
from [table] t
where type = '1'
order by id desc
Try naming the tables:
SELECT *
FROM Table AS a
WHERE id = (SELECT MAX(b.id) FROM Table AS b WHERE b.type = 1)
After a while on google, find that SQLCE in version 3.5 support SELECT TOP expression, but with difference with formating. It must be write with brackets
SELECT TOP(1) * FROM MyTable

How can I count the number of columns in a MySQL table using C#?

I can select the number of rows returned by a query when I select everything by doing the following:
SELECT Count(*) FROM `foo`.`bar`;
However, I now want to select how many columns are returned. Is there an easy way to do this?
Use the information_schema database.
SELECT
COUNT(COLUMN_NAME) AS numcols
FROM COLUMNS
WHERE
TABLE_NAME = 'bar'
AND TABLE_SCHEMA = 'foo'
To put the two together, use:
SELECT
(SELECT COUNT(*) FROM foo.bar) AS numrows,
(SELECT
COUNT(COLUMN_NAME) AS numcols
FROM COLUMNS
WHERE
TABLE_NAME = 'bar'
AND TABLE_SCHEMA = 'foo'
) AS numcols
DESCRIBE someTable and then mysql_count_rows() on the result.
Since the question has to do with C#, I think this should work - but I haven't done C# in a long time.
MySqlConnection connection = new MySqlConnection(#...);
MySqlCommand command = connection.CreateCommand();
MySqlDataReader Reader;
command.CommandText = "DESCRIBE sometable";
connection.Open();
Reader = command.ExecuteReader();
Reader.FieldCount # this has the count of rows, and hence columns
If your table mydb.mytable is MyISAM, the following should work well:
SELECT
row_count,column_count
FROM
(
SELECT table_rows row_count
FROM information_schema.tables
WHERE table_schema = 'mydb'
AND table_name = 'mytable'
) rowcount,
(
SELECT MAX(ordinal_position) column_count
FROM information_schema.columns
WHERE table_schema = 'mydb'
AND table_name = 'mytable'
) columncount
;

Categories