OleDbConnection connection = new OleDbConnection(#"Provider = Microsoft.ACE.OLEDB.12.0; Data Source = E:\Computing\WindowsFormsApplication1\WindowsFormsApplication1\bin\Debug\Database31.accdb");
connection.Open();
OleDbCommand command = new OleDbCommand("SELECT Cocktails.CID, Ingredients.Ingredient1" +
" FROM Cocktails INNER JOIN Ingredients" +
" ON Cocktails.ID = Ingredients.ID" +
" WHERE Cocktails.ID = 1",
connection);
OleDbDataReader reader = command.ExecuteReader();
if (reader.Read())
{
string result = reader.GetValue(0).ToString();
string result2 = reader.GetValue(1).ToString();
MessageBox.Show(result + result2);
}
connection.Close();
I'm new to SQL and trying to pull information from two different tables using an 'inner join', : 'Syntax error in JOIN operation.'
is the error I'm getting and unsure why. Thanks
Cocktail and Ingredient must be Cocktails and Ingredients, just like you have them in the FROM ... INNTER JOIN line
The table names you specified is wrong.
ON Cocktails.ID = Ingredients.ID
Related
I am new to Programming and I started with C# (Visual Studio 2017 CE);
I am writing an application and using a DataGrid. I am trying to fill the DataGrid using a query to a C# service based DB (mdf file).
When I run the app and try the query statement I get this error:
Operand type clash: date is incompatible with int
at the SqlDataReader Line.
I have tested the SQL Select statement in the SQL Server and it works there. I have read multiple questions related to the error, but since I am a rookie to programming almost all answers are difficult to understand, Thanks in advance for your understanding
using (SqlConnection conn = Conexion.Conectado())
{
string strsql = "SELECT dbo.Personas.Nombres, dbo.Personas.Apellidos, dbo.Prestamo.prestamo_id, dbo.Prestamo.fecha, dbo.Prestamo.Monto_prestamo, dbo.Prestamo.Ruta, dbo.Prestamo.Quotas, dbo.Prestamo.Balance, dbo.Registro_pagos.Monto_pago, dbo.Registro_pagos.Mora FROM dbo.Personas INNER JOIN dbo.Prestamo ON dbo.Personas.Persona_id = dbo.Prestamo.fk_Persona_id INNER JOIN dbo.Registro_pagos ON dbo.Prestamo.prestamo_id = dbo.Registro_pagos.fk_prestamo_id where dbo.Registro_pagos.fecha_pago = " + Dtp_fecha_cuadre.Text;
SqlCommand cmd = new SqlCommand(strsql, conn);
cmd.CommandType = CommandType.Text;
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
string Nombres = dr["Nombres"].ToString();
string Apellidos = dr["Apellidos"].ToString();
string num_prestamo = dr["prestamo_id"].ToString();
DateTime fecha = Convert.ToDateTime(dr["fecha"].ToString());
double Monto_prestamo = Convert.ToDouble(dr["Monto_prestamo"].ToString());
string Codigo_ruta = dr["Ruta"].ToString();
string Quotas = dr["Quotas"].ToString();
double Balance = Convert.ToDouble(dr["Balance"].ToString());
double Monto_pago = Convert.ToDouble(dr["Monto_pago"].ToString());
double Mora = Convert.ToDouble(dr["Mora"].ToString());
Dgv_cuadre_rutas.Rows.Add(Nombres, Apellidos, num_prestamo, fecha,Monto_prestamo , Codigo_ruta, Quotas, Balance, Monto_pago, Mora);
}
conn.Close();
}
Uses SQL DataAdapter instead which is much easier and will get rid of error
using (SqlConnection conn = Conexion.Conectado())
{
string strsql = "SELECT dbo.Personas.Nombres, dbo.Personas.Apellidos, dbo.Prestamo.prestamo_id, dbo.Prestamo.fecha, dbo.Prestamo.Monto_prestamo, dbo.Prestamo.Ruta, dbo.Prestamo.Quotas, dbo.Prestamo.Balance, dbo.Registro_pagos.Monto_pago, dbo.Registro_pagos.Mora FROM dbo.Personas INNER JOIN dbo.Prestamo ON dbo.Personas.Persona_id = dbo.Prestamo.fk_Persona_id INNER JOIN dbo.Registro_pagos ON dbo.Prestamo.prestamo_id = dbo.Registro_pagos.fk_prestamo_id where dbo.Registro_pagos.fecha_pago = " + Dtp_fecha_cuadre.Text;
SqlCommand cmd = new SqlCommand(strsql, conn);
cmd.CommandType = CommandType.Text;
SqlDataAdapter adapter = new SqlDataAdapter(strsql, conn);
DataTable dt = new DataTable();
adapter.Fill(dt);
Dgv_cuadre_rutas.DataSource = dt;
conn.Close();
}
I was able to fix the error! the error occurs first because in my original query I was using " = " + Dtp_fecha_cuadre.Text;" the equal sends the data in an int format, so I had to change it to "--like '" + Dtp_fecha_cuadre.Value.ToString() +"'";,-- but at this point it was not filling up the datagrid, then I came up with the idea that, date string being send was not in the correct format, and adjusted the query to "like '" + Dtp_fecha_cuadre.Value.ToString("yyyy-MM-dd") +"'"; and this solve my problem, thanks all that helped me here – engel 1 min ago edit
using (SqlConnection conn = Conexion.Conectado())
{
string strsql = "SELECT dbo.Personas.Nombres, dbo.Personas.Apellidos, dbo.Prestamo.prestamo_id, dbo.Prestamo.fecha, dbo.Prestamo.Monto_prestamo, dbo.Prestamo.Ruta, dbo.Prestamo.Quotas, dbo.Prestamo.Balance, dbo.Registro_pagos.Monto_pago, dbo.Registro_pagos.Mora FROM dbo.Personas INNER JOIN dbo.Prestamo ON dbo.Personas.Persona_id = dbo.Prestamo.fk_Persona_id INNER JOIN dbo.Registro_pagos ON dbo.Prestamo.prestamo_id = dbo.Registro_pagos.fk_prestamo_id where dbo.Registro_pagos.fecha_pago like '" + Dtp_fecha_cuadre.Value.ToString("yyyy-MM-dd") +"'";
SqlCommand cmd = new SqlCommand(strsql, conn);
cmd.CommandType = CommandType.Text;
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
string Nombres = dr["Nombres"].ToString();
string Apellidos = dr["Apellidos"].ToString();
string num_prestamo = dr["prestamo_id"].ToString();
DateTime fecha = Convert.ToDateTime(dr["fecha"].ToString());
double Monto_prestamo = Convert.ToDouble(dr["Monto_prestamo"].ToString());
string Codigo_ruta = dr["Ruta"].ToString();
string Quotas = dr["Quotas"].ToString();
double Balance = Convert.ToDouble(dr["Balance"].ToString());
double Monto_pago = Convert.ToDouble(dr["Monto_pago"].ToString());
double Mora = Convert.ToDouble(dr["Mora"].ToString());
Dgv_cuadre_rutas.Rows.Add(Nombres, Apellidos, num_prestamo, fecha, Monto_prestamo, Codigo_ruta, Quotas, Balance, Monto_pago, Mora);
}
conn.Close();
I can use this loop to give me list of names:
string commandText = #"SELECT ....;";
string connectionString = ConfigurationSettings.AppSettings["connectionString"];
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(commandText, connection);
try
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
DataTable dt = new DataTable();
dt.Load(reader);
for (int i = dt.Rows.Count - 1; i >= 0; i--)
{
SqlCommand addresscommand = new SqlCommand(address, connection);
addresscommand.Parameters.AddWithValue("#companyName", dt.Rows[i][0].ToString());
SqlDataReader addressreader = command.ExecuteReader();
string address = addressreader.GetString(0);
}
}
}
catch (Exception ex)
{
}
}
so the dt.Rows[i][0].ToString() is the name I need to add to all my different sql commands. So inside that for loop I will get each value from executing each sql command, one by one:
SqlCommand addresscommand = new SqlCommand(address, connection);
addresscommand.Parameters.AddWithValue("#companyName", dt.Rows[i][0].ToString());
SqlDataReader addressreader = addresscommand.ExecuteReader();
string comaddress = addressreader.GetString(0);
SqlCommand keyProcessescommand = new SqlCommand(keyProcesses, connection);
keyProcessescommand.Parameters.AddWithValue("#companyName", dt.Rows[i][0].ToString());
SqlDataReader keyProcessesreader = keyProcessescommand.ExecuteReader();
string comkeyProcesses = keyProcessesreader.GetString(0);
SqlCommand standardscommand = new SqlCommand(standards, connection);
standardscommand.Parameters.AddWithValue("#companyName", dt.Rows[i][0].ToString());
SqlDataReader standardsreader = standardscommand.ExecuteReader();
string comstandards = standardsreader.GetString(0);
Where the command string determined by:
string address = #"SELECT address FROM Companies where companyName = #companyName";
string keyProcesses = #" SELECT distinct STUFF((SELECT ', '+ cn.name from WMCCMCategories cn
INNER JOIN CategorySets uc ON uc.categoryId = cn.categoryID
INNER JOIN KeyProcesses u ON u.categorySetId = uc.setId
INNER JOIN Companies c ON c.companyId = u.companyId
WHERE c.companyName = #companyName
ORDER BY cn.name
FOR XML PATH('')), 1, 1, '') AS listStr
FROM WMCCMCategories cnn Group by cnn.name";
string standards = #" SELECT cn.name from WMCCMCategories cn
INNER JOIN CategorySets uc ON uc.categoryId = cn.categoryID
INNER JOIN Companies c ON c.standards = uc.setId
WHERE c.companyName = #companyName";
Can I execute multiple sql commands like above? How is the best way to do that ?
One way you can solve this through JOIN in SQL. However, it may not be right thing to do if it is not representing same columns.
Now in terms of using multiple select in one command. Yes, you can use SqlDataReader with NextResult()
Please see this link:
http://csharp.net-informations.com/data-providers/csharp-multiple-resultsets.htm
string query = "select a.Name,a.Add from GroupDetails a join General b on a.ID=b.Id where b.AccCode='" + label1.text + "'";
OleDbCommand cmd = new OleDbCommand(query, con);
OleDbDataAdapter daName = new OleDbDataAdapter(cmd);
OleDbDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
txtName.Text = dr["a.Name"].ToString();
txtAdd.Text = dr["a.Add"].ToString();
}
There shows an exception
Syntax error in FROM clause
If it explicitly mentions from, then my guess would be that the SQL backend doesn't support aliases (the a). However, there are multiple problems:
the alias
the sql concatenation
the unnecessary adapter
the incorrect columns being read
I would suggest trying:
const string query = "select GroupDetails.Name,GroupDetails.Add from GroupDetails join General on GroupDetails.ID=General.Id where General.AccCode=#accCode";
using(var cmd = new OleDbCommand(query, con))
{
cmd.Parameters.AddWithValue("accCode", label1.text);
using(var dr = cmd.ExecuteReader())
{
txtName.Text = (string)dr["Name"];
txtAdd.Text = (string)dr["Add"];
}
}
I'm sure that your query is not SQL Server because it works OK in SQL Server query window. It could be Access SQL or My SQL, and you have to specify explicitly left join, right join or inner join. I think you want inner join in this case:
string query = "SELECT a.Name,a.Add FROM GroupDetails a INNER JOIN General b ON a.ID=b.Id WHERE b.AccCode='" + label1.text + "'";
Add is the Keyword of SQL, you can [] the field like a.[Add]
string query = "select a.Name,a.[Add] from GroupDetails a join General b on a.ID=b.Id where b.AccCode='" + label1.text + "'";
My code:
SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString);
SqlCommand cmd = new SqlCommand();
//..........
cmd.CommandText = "SELECT * FROM TempQn WHERE creatorId= '" +
Session["administratorID"].ToString() + "'";
dr = cmd.ExecuteReader();
while (dr.Read())
{
int ids = Int32.Parse(dr["QuestionID"].ToString());
cmd.CommandText = " INSERT INTO Answers (QuestionId,Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = " + ids + " ";
cmd.ExecuteNonQuery(); //this line
}
dr.Close();
The error is:
There is already an open DataReader associated with this Command which must be closed first.
What kind of command should replace the cmd.ExecuteNonQuery();?
You can't execute any further SQL statements as long as the DataReader is "active".
To overcome this, store list of the SQL statements then exeucute them after reading:
cmd.CommandText = "SELECT * FROM Question WHERE SurveyID= '" + sID + "'";
dr = cmd.ExecuteReader();
List<string> arrSQL = new List<string>();
while (dr.Read())
{
int ids = Int32.Parse(dr["QuestionID"].ToString());
arrSQL.Add("INSERT INTO Answers (QuestionId,Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = " + ids + " ");
}
dr.Close();
arrSQL.ForEach(strSQL =>
{
cmd.CommandText = strSQL;
cmd.ExecuteNonQuery();
});
Your current code is vulnerable to SQL injection attacks though and isn't good practice - you better use Parameter instead of injecting value to the raw SQL - here is how to achieve that:
cmd.CommandText = "SELECT * FROM Question WHERE SurveyID=#id";
cmd.Parameters.AddWithValue("#id", sID);
dr = cmd.ExecuteReader();
List<int> arrQuestions = new List<int>();
while (dr.Read())
{
int ids = Int32.Parse(dr["QuestionID"].ToString());
arrQuestions.Add(ids);
}
dr.Close();
cmd.CommandText = "INSERT INTO Answers (QuestionId, Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = #id";
arrQuestions.ForEach(id =>
{
cmd.Parameters["#id"].Value = id;
cmd.ExecuteNonQuery();
});
You already have one command associated with "cmd".
dr = cmd.ExecuteReader();
while (dr.Read())
{
int ids = Int32.Parse(dr["QuestionID"].ToString());
SqlCommand sqlCmd = new SqlCommand("INSERT INTO Answers (QuestionId,Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = " + ids + " ");
sqlCmd.ExecuteNonQuery(); //this line
}
dr.Close();
So Like ive given above create a new command for the insertion.
This single query should do the job (not sure of you exact data model, adapt if required ):
INSERT INTO Answers (QuestionId,Answer)
Select c.QnId, c.Answer
From TempAns c
inner join Question q on c.QnId = q.Id
where q.SurveyID = #SurveyID
In order to avoid SQl Injection, use this C# code :
cmd.CommandTest = #"INSERT INTO Answers (QuestionId,Answer)
Select c.QnId, c.Answer
From TempAns c
inner join Question q on c.QnId = q.Id
where q.SurveyID = #SurveyID";
SqlParameter param = cmd.Parameters.Add("#SurveyID", SqlDbType.Int);
param.Value = yourSurveyId;
cmd.Open(); // it would be better to check the status before
cmd.ExecuteNonQuery();
cmd.Close();
Instead of using a 2nd connection object, you could change your connection string and use MARS (Multiple active result set) for this purpose. Add the following statement to your connection string:
MultipleActiveResultSets=True
EDIT:
And like the other's said, use SqlParameters for your parameters and not string concatenation. It's not only a security issue, but also a huge performance hit!
you need to declare a new command object because cmd is already being used for reading the data when you are trying to use it for insert statement. Also, don't use string concatenation from sql command, its a bad practice and vulnerable to SQL injection. using parameters.
I am trying to update a set of queries using .NET's DataAdapter. Here's a simplified version of what I'm doing:
//get all transactions that need to be made
String sql = "SELECT r.ID, r.[Check], r.Cash, r.Coin, r.TenantID, t.TenantName, r.PropertyID, u.UnitNumber, r.ReceivedFrom, r.isDeposited FROM tblCashReceipts r " + //I don't actually think all this is needed, if nessecary I can go back and remove unnessecary selections
"LEFT JOIN tblTenant t " +
"ON t.ID = r.TenantID " +
"LEFT JOIN tblProperty p " +
"ON p.ID = r.PropertyID " +
"LEFT JOIN tblRentalUnit u " +
"ON t.UnitID = u.id " +
"WHERE p.CheckbookID = " + checkbookId;
//populate the data table
DataTable receipts = new DataTable();
using (SqlConnection conn = new SqlConnection(connectionString)) {
conn.Open();
SqlDataAdapter adapter = new SqlDataAdapter(sql, conn);
try {
adapter.Fill(receipts);
} catch (Exception ex) {
MessageBox.Show(ex.Message);
} finally {
conn.Close();
}
}
//update the row
foreach (DataRow row in receipts.Rows) {
//no longer removing, it will be left entact with the hidden tblCashReceipt row
row["isDeposited"] = true;
}
//now make the database reflect our changes to the tblCashReceiptes
using (SqlConnection conn = new SqlConnection(connectionString)) {
SqlDataAdapter receiptsAdapter = new SqlDataAdapter("SELECT ID FROM tblCashReceipts", connectionString);
//create delete command
conn.Open();
SqlCommand receiptsUpdateCommand = new SqlCommand("UPDATE tblCashReceipts SET isDeposited = #isDeposited WHERE ID = #ID", conn);
SqlParameter idParam = receiptsUpdateCommand.Parameters.Add("#ID", SqlDbType.Int, 5, "ID");
idParam.SourceVersion = DataRowVersion.Original;
SqlParameter depositiedParam = receiptsUpdateCommand.Parameters.Add("#isDeposited", SqlDbType.Bit, 1, "isDeposited");
depositiedParam.SourceVersion = DataRowVersion.Original;
receiptsAdapter.UpdateCommand = receiptsUpdateCommand;
receiptsAdapter.Update(receipts);
}
However, I find that the receiptsAdapter.Update(receipts); doesn't actually result in the database being updated. What am I doing wrong?
A simplified way of writing this would be just to execute the sql command of: UPDATE tblCashReceipts SET isDeposited = 1 WHERE {my clause} But I want to learn how to use ADO.NET stuff.
below line is having problem
depositiedParam.SourceVersion = DataRowVersion.Original;
it must be
depositiedParam.SourceVersion = DataRowVersion.Current;