I am trying to retrieve a distinct row from my Database from a particular "deliverySerial".
However I encountered an error which prompt me to "Declare Scalar Variable ="#deliverySerial".
I had tried many other ways but still problems still persist.
Here is the connection:
public class DlDbConn
{
public DlDbConn()
{
}
public SqlConnection GetConnection()
{
SqlConnection dbConn;
dbConn = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\test.mdf;Integrated Security=True;User Instance=True");
return dbConn;
}
}
Method in the data layer:
private String errMsg;
private DlDbConn dbConn;
public testing()
{
dbConn = new DlDbConn();
}
public DataSet Details(String supplierLogo, String supplierName, String supplierAddr, int poNum, String dateSent, int deliverySerial, String deliveryDate,
int quantity, String catSerial, String catName)
{
SqlConnection conn;
StringBuilder sql;
SqlDataAdapter da;
DataSet detail;
conn = dbConn.GetConnection();
detail = new DataSet();
sql = new StringBuilder();
sql.AppendLine("SELECT * FROM (select PO.poNum, PO.dateSent, ViewDelivery.deliverySerial, Supplier.supplierName, Supplier.supplierAddr, Supplier.supplierLogo, ViewDelivery.deliveryDate, Catalog.catSerial, Catalog.catName, PO.quantity, ROW_NUMBER() OVER (PARTITION BY Catalog.catSerial ORDER BY Catalog.catSerial) AS num FROM PO INNER JOIN Supplier ON PO.supplierID = Supplier.supplierID INNER JOIN ViewDelivery ON PO.poNum = ViewDelivery.poNum INNER JOIN Catalog ON PO.catSerial = Catalog.catSerial)AS a WHERE a.num = 1 ");
sql.AppendLine("AND ViewDelivery.deliverySerial = #deliverySerial");
try
{
conn.Open();
da = new SqlDataAdapter(sql.ToString(), conn);
da.SelectCommand.Parameters.AddWithValue("#deliverySerial", deliverySerial);
da.Fill(detail);
}
catch (Exception ex)
{
errMsg = ex.Message;
}
finally
{
conn.Close();
}
return detail;
}
You must use parameter notation for MySQL i.e. ? instead of #deliverySerial in your query.
Also, table ViewDelivery not accessible in outer part of query.
Use:
AND a.deliverySerial = ?
I think your query is incorrect. Here is the Fiddle -- you can't query on ViewDelivery since it's outside of your subquery.
Try removing that from your WHERE criteria since that field is returned in your subquery:
sql.AppendLine("AND deliverySerial = #deliverySerial");
I don't think you need the "?", but I could be mistaken.
Good luck.
Related
I run the VS file to the following code. After start running, it shows System.Data.OleDb.OleDbException: 'Syntax error in FROM clause.'
How can I solve it? Thank you.
public partial class OrderForm : Form
{
OleDbConnection con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=db_users.accdb");
OleDbCommand command = new OleDbCommand();
OleDbDataReader dr;
public OrderForm()
{
InitializeComponent();
LoadOrder();
}
public void LoadOrder()
{
double total = 0;
int i = 0;
dgvOrder.Rows.Clear();
command = new OleDbCommand("SELECT OrderID,OrderDate,O.[ProductID],P.[ProdName], O.[CustID], C.[CustName], Qty, Price, Total FROM [Order] AS O JOIN [Customer] AS C ON O.[CustID]=C.[CustID] JOIN [Product] AS P ON O.[ProductID]=P.[ProductID] WHERE CONCAT(OrderID,OrderDate,O.[ProductID],P.[ProdName], O.[CustID], C.[CustName]) LIKE '%" +txtSearch.Text+"%'", con);
con.Open();
dr = command.ExecuteReader();
while (dr.Read())
{
i++;
dgvOrder.Rows.Add(i, dr[0].ToString(), Convert.ToDateTime(dr[1].ToString()).ToString("dd/MM/yyyy"), dr[2].ToString(), dr[3].ToString(), dr[4].ToString(), dr[5].ToString(), dr[6].ToString(), dr[7].ToString(), dr[8].ToString());
total += Convert.ToInt32(dr[8].ToString());
}
dr.Close();
con.Close();
lblQty.Text = i.ToString();
lblTotal.Text = total.ToString();
}
with the information provided by your code, I have created 3 tables to simply reproduce your code.The data in the table in the database is filled in casually, please understand.
form page:
By clicking the "Query Condition" button, you can generate data in the form by querying the database.
this is the result:
The operation of the database is encapsulated by the entity class, which is the code that encapsulates the database entity class.
internal class Dao
{
SqlConnection conn;
public SqlConnection connection()
{
// write database connection string
string connStr = "Data source=localhost;Initial Catalog=test;User ID=sa;Password=123456";
conn = new SqlConnection(connStr);
conn.Open();
return conn;
}
public SqlCommand command(string sql)
{
SqlCommand cmd = new SqlCommand(sql, connection());
return cmd;
}
public int Execute(string sql)
{
return command(sql).ExecuteNonQuery();
}
public SqlDataReader read(string sql)
{
return command(sql).ExecuteReader();
}
public void DaoClose()
{
conn.Close();
}
}
By clicking the button, the function of querying the database is realized and the corresponding data is generated.
//Read the data from the data and display it in the table control
public void Table()
{
dataGridView1.Rows.Clear();// clear old data
Dao dao = new Dao();
double total = 0;
int i = 0;
string sql = $"SELECT OrderID,OrderDate,O.[ProductID],P.[ProdName], O.[CustID], C.[CustName], Qty, Price, Total FROM [Orders] AS O JOIN [Customer] AS C ON O.[CustID]=C.[CustID] JOIN [Product] AS P ON O.[ProductID]=P.[ProductID] WHERE CONCAT(OrderID,OrderDate,O.[ProductID],P.[ProdName], O.[CustID], C.[CustName]) LIKE '%{textBox1.Text}%'";
IDataReader dr = dao.read(sql);
while (dr.Read())
{
i++;
dataGridView1.Rows.Add(i, dr[0].ToString(), Convert.ToDateTime(dr[1].ToString()).ToString("dd/MM/yyyy"), dr[2].ToString(), dr[3].ToString(), dr[4].ToString(), dr[5].ToString(), dr[6].ToString(), dr[7].ToString(), dr[8].ToString());
total += Convert.ToInt32(dr[8].ToString());
}
dr.Close();
dao.DaoClose();
lblQty.Text = i.ToString();
lblTotal.Text = total.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
Table();
}
Through the test, there is no problem with the sql statement, the function of database query is realized and the data is successfully displayed. Check the database connection string. Whether the fields of the sql statement correspond to the database. Hope that helps you.
I'm trying to write a function -like Dcount and Dlookup in VBA Access- in a public class to use it everywhere in my project so I did the following :
public class MyTools
{
SqlConnection Cn = new SqlConnection(#"Server = AMR-PC\SQLEXPRESS ; Database=PlanningDB ; Integrated Security = True");
SqlDataAdapter da;
DataTable dt = new DataTable();
// DataView dv = new DataView();
SqlCommand cmd;
SqlDataReader DataRead;
// Variables
string MyColumn, MyTable, MyCondition,DlookResult;
int DcountResult;
// Methods & Functions
// Dcount
public int DCount(string MyColumn, string MyTable, string MyCondition)
{
da = new SqlDataAdapter("Select Count(#MyColumn) from #MyTable where #MyColumn = #MyCondition", Cn);
da.Fill(dt);
DcountResult = int.Parse(dt.Rows[0].ToString());
return DcountResult;
}
}
// Dlookup
}
And tried to use it like this :
int Result = DCount(txtColumn.Text, txtTable.Text, txtCond.Text);
txtResult.Text = null;
txtResult.Text = Result.ToString();
But it throws the error "Must declare the scalar variable "#MyColumn".
I tried to use sqlcommand and DataRead but I need to close the connection after the return and it became Unreachable or close before the return so it returns nothing , That's why i used SqlDataAdapter.
Thanks in advance .
It would have to look something more like this:
public class MyTools
{
private static string ConnectionString {get;} = #"Server = AMR-PC\SQLEXPRESS ; Database=PlanningDB ; Integrated Security = True";
public static int DCount(string MyTable, string MyColumn, string MyCondition)
{
string sql = $"Select Count({MyColumn}) from {MyTable} where {MyColumn} = #MyCondition";
using (var cn = new SqlConnection(ConnectionString))
using (var cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.AddWithValue("#MyCondition", MyCondition);
cn.Open();
return (int)cmd.ExecuteScalar();
}
}
}
Just be aware this uses dynamic SQL, and is more than a little dangerous. In fact, you should not do this. I know you don't want to "keep typing SQL queries", but that might be exactly what you should do.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
What should I do with this error? I used this code in selectall method and everything was fine, but in selectrow I get this error.
Code:
public DataTable SelectRow(string ContactID)
{
string query = "Select * from ContactsList Where ContactID = #ID";
SqlConnection connection = new SqlConnection(ConnectionString);
SqlDataAdapter adapter = new SqlDataAdapter(query, connection);
DataTable data = new DataTable();
adapter.Fill(data);
return data;
}
Error:
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information:
Must declare the scalar variable "#ID".
The following code
Creates a parameter as a parameter should be done and as recommended by #Olivier Rogier.
Does not use a DataAdapter, seeing you have it as a local var indicates this. Use a command object instead.
Note the return type carries the DataTable if no errors while if a runtime exception is raised the Exception is passed back to the caller.
Recommend not using SELECT * (not part of the question but better to ask for that which is needed and no more).
Code
public class DataOperations
{
private static string connection = "Data Source=.\\sqlexpress;Initial Catalog=NorthWind2020;Integrated Security=True";
public static (DataTable table, Exception exception) SelectRow(string contactId)
{
DataTable table = new DataTable();
try
{
using (var cn = new SqlConnection { ConnectionString = connection })
{
using (var cmd = new SqlCommand { Connection = cn })
{
cmd.CommandText = "SELECT FirstName, LastName FROM dbo.Contacts WHERE ContactId = #contactId;";
cmd.Parameters.Add("#contactId", SqlDbType.NVarChar).Value = contactId;
cn.Open();
table.Load(cmd.ExecuteReader());
return (table, null);
}
}
}
catch (Exception exception)
{
return (null, exception);
}
}
}
Sample code to call method above.
var (dataTable, exception) = DataOperations.SelectRow(contactIdentifier);
if (exception == null)
{
Debug.WriteLine("Use table");
}
else
{
Debug.WriteLine(exception.Message);
}
Also, if the contact identifier is pointing to a single record you could simply pass a single DataRow back rather than an entire DataTable or use a single instance of a class e.g.
public class Contact
{
// seems this would be an int
public string ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString() => $"{FirstName} {LastName}";
}
Code to get data
public static Contact SelectContact(string contactId)
{
Contact contact = new Contact() {ContactId = contactId};
using (var cn = new SqlConnection { ConnectionString = connection })
{
using (var cmd = new SqlCommand { Connection = cn })
{
cmd.CommandText = "SELECT FirstName, LastName FROM dbo.Contacts WHERE ContactId = #contactId;";
cmd.Parameters.Add("#contactId", SqlDbType.NVarChar).Value = contactId;
cn.Open();
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
contact.FirstName = reader.GetString(0);
contact.LastName = reader.GetString(1);
}
}
}
return contact;
}
Passing Scalar Variable to SQL Raw Query (Must declare the scalar variable)
You have declared the parameter #ID but didn't pass the value for the parameter.
I have modified your code as below.
public DataTable SelectRow(string ContactID)
{
SqlConnection connection = new SqlConnection(ConnectionString);
string query = "Select * from ContactsList Where ContactID = #ID";
SqlCommand cmd=new SqlCommand(query,connection);
cmd.CommandType=CommandType.Text;
cmd.Parameters.AddWithValue("#ID",ContactID);
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataTable data = new DataTable();
adapter.Fill(data);
return data;
}
You can pass the SqlCommand object "cmd" to the SqlDataAdapter constructor which will load the data as per the specified query to the "adapter" object.
Hoping that the above code will be helpful to you.
I am trying to show number of rows from a grid view using a label. I used SQL Count statement but it doesn't work. The problem is I only get only number 1 shown in the label which is not matched with the number of rows I have in my table! I have posted similar question but unfortunately no body gave a clear answer!
My codes as:
Basket.ac
public int td()
{
int customers;
//I tried this select query but still gets number 1
//String sql = String.Format("SELECT COUNT(*) FROM dbo.Baskets");
string sql = string.Format("SELECT COUNT(*) FROM Baskets");
customers = Db.RunQuery(sql).Rows.Count;
//customers = Convert.ToInt32(Db.RunQuery(sql).Rows.Count);
return customers;
}
DataBaseConn.ac
public class DataBaseConn
{
SqlConnection conn;
SqlCommand cmd;
DataTable tbl;
private void Intialise(CommandType commandtype, string DataBase)
{
conn = new SqlConnection();
cmd = new SqlCommand();
//Requirements
conn.ConnectionString = ConfigurationManager.ConnectionStrings[1].ToString();
cmd.Connection = conn;
cmd.CommandType = commandtype;
cmd.CommandText = DataBase;
conn.Open();
}
public int RunProcedure(string Procedure, SortedList ParameterV)
{
Intialise(CommandType.StoredProcedure, Procedure);
for (int i = 0; i < ParameterV.Count; i++)
try
{
if (ParameterV.GetByIndex(i) != null)
cmd.Parameters.AddWithValue(ParameterV.GetKey(i).ToString(),
PrameterV.GetByIndex(i).ToString());
}
catch { ;}
return RunUpdate();
}
public int RunUpdate(string InsDelUpd)
{
Intialise(CommandType.Text, InsDelUpd);
return RunUpdate();
}
private int RunUpdate()
{
try
{
int x = cmd.ExecuteNonQuery();
conn.Close();
return x;
}
catch (SqlException ex)
{
conn.Close();
return ex.Number;
}
}
public DataTable RunQuery(string Select)
{
Intialise(CommandType.Text, Select);
tbl = new DataTable();
tbl.Load(cmd.ExecuteReader());
conn.Close();
return tbl;
}
public bool EData(string selection)
{
if (RunQuery(selection).Rows.Count > 0)
return true;
else
return false;
}
}
Basket.aspx
lblQueue.Text = _b.td().ToString();
You don't want to return the data table's .Rows.Count - this will always be 1 (as in 1 row(s) affected) for your count(*) query.
You should instead look at using ExecuteScalar to return the first column of the first row from your query
I'm not sure how you want to build this into your DataBaseConn data helper class, but the gist of it is you need the following sequence:
using (var conn = new SqlConnection(connectionStringHere))
using (var cmd = new SqlCommand(conn))
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT COUNT(*) FROM Baskets";
return (int)cmd.ExecuteScalar();
}
Edit
If you aren't able to extend your DataBaseConn helper with an ExecuteScalar, then I guess you'll be able to use the existing RunQuery method which returns a DataTable. Just scrape the first column of the first row like so:
return Db.RunQuery(sql).Rows[0].Field<int>(0);
As a side note, you might look at replacing your DataHelper entirely with the Microsoft Patterns and Practices Data Application Access Block (DAAB), or, if you prefer, look at using an ORM like Entity Framework. By upgrading to a mainstream Data Access encapsulation, you won't need to spend as much time debugging data access issues like this one :)
I tried to convert a datatable that just has one field (the field's data is primary key) to int , in order to using in sql commands such as Select and etc.
but it fails!
and when i cast it to an object or convert it to string first , the commands gone wrong!
please help me
i want to select * from a table which has a foreign key where the foreign code equals by an int value that has been selected from a table in another sql command and returned as a datatable row with just one field.
here is my code :
class mydata :
public string strsql;
public DataTable showData()
{
SqlConnection Con1 = new SqlConnection("Data Source=.;database=daneshgah;integrated security=true");
Con1.Open();
SqlDataAdapter da = new SqlDataAdapter(strsql, Con1);
DataTable dt = new DataTable();
da.Fill(dt);
Con1.Close();
return (dt);
}
button event :
myData search = new myData();
int aa = int.Parse(txt_stdcourse.Text);
search.strsql = "select tchNo from University where couNo='" + aa + "'";
DataTable a = search.showData();
string b = a.Rows[0][0].ToString();
int c = int.Parse(b);
myData akhz = new myData();
akhz.strsql = "insert into stc (couNo,tchNo,stuNo)values('" + aa + "','" + c + "','" + id + "')";
akhz.Data();
lbl_stdcourseok.Visible = false;
lbl_stdcourseok.Visible = true;
Sounds like you need to use ExecuteScalar on a SqlCommand instead of using a DataAdapter. ExecuteScalar gives the first column of the first row of the dataset returned.
public object RunSQL(string sql)
{
SqlConnection Con1 = new SqlConnection("Data Source=.;database=daneshgah;integrated security=true");
Con1.Open();
SqlCommand command = new SqlCommand(strsql, Con1);
return command.ExecuteScalar();
}
//In some event handler
int myValue = (int)RunSQL("Select Value from Table where ID = " + ID);
That said, please don't do that - it is very bad practice. You almost certainly want to create a class that models whatever data objects you are dealing with, instead of executing arbitrary SQL from event handlers. It is also probably best to manage connections independently of your data class, in a separate data access layer.
An extremely rudimentary example:
public class Student
{
public int StudentID { get; set; }
public bool CurrentlyEnrolled { get; set; }
public string Name { get; set; }
public static Student LoadByID(int ID)
{
DataTable results = DAL.ExecuteSQL("Select * from Students WHERE StudentID = #StudentID", new SqlParameter("#StudentID", ID));
if (results.Rows.Count == 1)
{
return FillFromRow(results.Rows[0]);
}
else
{
throw new DataException("Could not find exactly one record with the specified ID.");
}
}
private static Student FillFromRow(DataRow row)
{
Student bob = new Student();
bob.CurrentlyEnrolled = (bool)row["CurrentlyEnrolled"];
bob.Name = (string)row["Name"];
bob.StudentID = (int)row["StudentID"];
return bob;
}
}
public static class DAL
{
private const string ConnectionString = "SomeConnectionString"; //Should really be stored in configuration files.
public static DataTable ExecuteSQL(string SQL, params SqlParameter[] parameters)
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
using (SqlCommand command = new SqlCommand(SQL))
{
command.Parameters.AddRange(parameters);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
DataTable result = new DataTable();
adapter.Fill(result);
return result;
}
}
}
}
}