mysql query truncated after increasing 'max_allowed_packet' - c#

I have a stored procedure in c# that I add values to and then execute:
string query = "INSERT INTO equipment_parameter (parameter_group_name, version, operation_name, parameter_name, parameter_value, default, owner, date_created) VALUES(#parameter_group_name, #version, #operation_name, #parameter_name, #parameter_value, #default, #owner, #date_created)"; //stored procedure
//open connection
if (mySQLA.OpenConnection() == true)
{
//create command
MySqlCommand cmd = new MySqlCommand();
cmd.Connection = mySQLA.getConnection();
cmd.CommandText = query;
cmd.Prepare();
//string
cmd.Parameters.AddWithValue("#parameter_group_name", eParam.ParameterGroupName);
//int
cmd.Parameters.AddWithValue("#version", eParam.Version);
//string
cmd.Parameters.AddWithValue("#operation_name", eParam.OperationName);
//string
cmd.Parameters.AddWithValue("#parameter_name", eParam.ParameterName);
//double
cmd.Parameters.AddWithValue("#parameter_value", eParam.ParameterValue);
//bool
cmd.Parameters.AddWithValue("#default", eParam.Default);
//string
cmd.Parameters.AddWithValue("#owner", eParam.Owner);
//DateTime
cmd.Parameters.AddWithValue("#date_created", eParam.DateCreated);
//Execute command
try
{
rowsCreated = cmd.ExecuteNonQuery(); //returns number of rows affected
}
catch (MySqlException es)
{
MessageBox.Show(es.Message, "Equipment Parameter Query Error: ");
}
When I run this program it attempts the insertion and then I catch the exception which states:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'default, owner, date_created) VALUES('object1', 1, 'Op1', 'object1', 10.01, 1, '' at line 1
The query I'm trying to execute would read something like:
INSERT INTO equipment_parameter (parameter_group_name, version, operation_name, parameter_name, parameter_value, default, owner, date_created) VALUES('object', 1, 'Op1', 'object1', 10.01, false, 'James', '2013-10-30 09:00:54')
I have already increased 'max_allowed_packet' to 500M and restarted the server though this had no effect. Are there other buffer-size options I can increase or what may be my problem?

After boiling my head with this I've just realised that default is a reserved word. As such, it has to be backticked:
[...] parameter_value, `default`, owner, date_created) [...]

Related

Insert new row to Database table if two fields does not match, otherwise sum value in certain column

I have data in Database table:
Here is the method for adding data:
public static void AddRecordToDatatable(string WindowTitle, int TimeSpent,
DateTime DateToday, string Project, string Username)
{
string sql = #"INSERT INTO dbo.Log (WindowTitle,TimeSpent,DateToday,Project,Username)" +
" VALUES (#WindowTitle,#TimeSpent,#DateToday,#Project,#Username)";
// Create the connection (and be sure to dispose it at the end)
using (SqlConnection cnn = new SqlConnection(DBconnectionString))
{
try
{
// Open the connection to the database.
// This is the first critical step in the process.
// If we cannot reach the db then we have connectivity problems
cnn.Open();
// Prepare the command to be executed on the db
using (SqlCommand cmd = new SqlCommand(sql, cnn))
{
// Create and set the parameters values
cmd.Parameters.Add("#WindowTitle", SqlDbType.NVarChar).Value = WindowTitle;
cmd.Parameters.Add("#TimeSpent", SqlDbType.Int).Value = TimeSpent;
cmd.Parameters.Add("#DateToday", SqlDbType.DateTime).Value = DateTime.Now.Date;
cmd.Parameters.Add("#Project", SqlDbType.NVarChar).Value = Project;
cmd.Parameters.Add("#Username", SqlDbType.NVarChar).Value = Username;
// Let's ask the db to execute the query
int rowsAdded = cmd.ExecuteNonQuery();
if (rowsAdded > 0)
{
//MessageBox.Show("Row inserted");
}
else
{
// This should never really happen, but let's leave it here
//MessageBox.Show("No row inserted");
}
}
cnn.Close();
}
catch (Exception ex)
{
// We should log the error somewhere,
// for this example let's just show a message
MessageBox.Show("ERROR:" + ex.Message);
}
}
}
How it is possible to check for existing record before inputting data to Database table and sum on certain value if it exists?
So basically check if WindowTitle = WindowTitle and DateToday = DateToday, if these two match, then take TimeSpent and sum it to existing TimeSpent in Database Table without inputting a new row.
I have tried to test ON DUPLICATE KEY UPDATE WindowTitle = #WindowTitle, DateToday = #DateToday after INSERT but Visual Studio is giving an error in Debugger for such a command pointing to ON (Incorrect syntax near ON). Also I am not sure if ON DUPLICATE is the best approach for this kind of case.
You need to expand your SQL to check for the existence of the record you think could exist.
IF EXISTS (SELECT 1 FROM dbo.Log WHERE WindowTitle = #WindowTitle AND DateToday = #DateToday)
BEGIN
--UPDATE HERE
END
ELSE
BEGIN
-- INSERT HERE
END
Alternatively you can create a query method and call that first, before calling AddRecordToDatatable
Personally I would do all of these CRUD operations using an ORM such as EF Core or preferably, NHibernate. But this all depends on requirements, limitations etc.

Return on my function doesn't work if using sql

I am populating a text box with the returned value of a function, but it doesn't work if I run the sql code inside the function. I can remove the sql related code and it works. so i'm stumped.
And by "doesn't work" i mean that the text box never gets populated with anything. it remains blank.
thanks
public string CreateResident()
{
string result = "hmm";
SqlConnection sqlConnection = new SqlConnection("Server=DELLXPS\\SQLEXPRESS; Initial Catalog=Warren_SEINDATASYSTEMS; Integrated Security=true;");
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "INSERT INTO [dbo].[NewUsers]([ResidentAccountNumber],[ResidentName],[ResidentAddress],[NumberOfVisitors],[TempPass],[Role])VALUES(#ResidentAccountNumber,#ResidentName,#ResidentAddress,#NumberOfVisitors,(select cast((Abs(Checksum(NewId()))%10) as varchar(1)) + char(ascii('a')+(Abs(Checksum(NewId()))%25)) + char(ascii('A')+(Abs(Checksum(NewId()))%25)) + left(newid(),5)),'resident')";
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection;
SqlParameter ResidentAccountNumber = new SqlParameter();
ResidentAccountNumber.ParameterName = "#ResidentAccountNumber";
ResidentAccountNumber.Value = txtboxResidenetAccountNumber.Text.Trim();
cmd.Parameters.Add(ResidentAccountNumber);
SqlParameter ResidentName = new SqlParameter();
ResidentName.ParameterName = "#ResidentName";
ResidentName.Value = txtboxResidentName.Text.Trim();
cmd.Parameters.Add(ResidentName);
SqlParameter ResidentAddress = new SqlParameter();
ResidentAddress.ParameterName = "#ResidentAddress";
ResidentAddress.Value = txtboxResidentAddress.Text.Trim();
cmd.Parameters.Add(ResidentAddress);
SqlParameter NumberOfVisitors = new SqlParameter();
NumberOfVisitors.ParameterName = "#NumberofVisitors";
NumberOfVisitors.Value = txtboxNumberOfVisitors.Text.Trim();
cmd.Parameters.Add(NumberOfVisitors);
try
{
sqlConnection.Open();
result = (string)cmd.ExecuteScalar();
sqlConnection.Close();
}
catch (Exception ex)
{
result = ex.Message;
}
return result;
}
protected void btnCreateResident_Click(object sender, EventArgs e)
{
txtboxTempPassword.Text = CreateResident();
}
Your SQL is wrong and you have a lot of problems but I want to show you a way to make your code more readable. Format it like this:
cmd.CommandText = #"INSERT INTO [dbo].[NewUsers] ([ResidentAccountNumber],[ResidentName],[ResidentAddress], NumberOfVisitors],[TempPass], Role])
VALUES(
#ResidentAccountNumber,
#ResidentName,
#ResidentAddress,
#NumberOfVisitors,
(select cast((Abs(Checksum(NewId()))%10) as varchar(1)) + char(ascii('a')+(Abs(Checksum(NewId()))%25)) + char(ascii('A')+(Abs(Checksum(NewId()))%25)) + left(newid(),5)),
'resident')";
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection;
We know that a select in a VALUES constructor is not legal so that is one problem.
Also having a SELECT without a from seems strange -- did you copy your code correctly?
You are using ExecuteScalar -- do you know what that does? It shouldn't include a query that includes INSERT query.
I'm guessing you probably want a stored procedure.
I would suggest do not write query in C# code, you must use Stored Procedure for the same purpose.
If you want your query to return some id, primary key or some value then you must write query for that after your insert query.
you can use the following keywords in your select query,if you want to return id from table.
SCOPE_IDENTITY returns the last IDENTITY value inserted into an IDENTITY column in the same scope.
IDENT_CURRENT returns the last identity value generated for a specific table in any session and any scope.
##IDENTITY returns the last identity value generated for any table in the current session, across all scopes.
If you want to return only one record then use ExecuteScalar else you can use ExecuteReader.
If your only purpose is to insert data into the table then you should use ExecuteNonQuery.
With the help of comments I went with ExecuteReader instead of the ExecuteScaler. And changed the statement to return a value
INSERT INTO [table] ([fields]) OUTPUT Inserted.MyColumn VALUES(values)
C# Code:
reader = cmd.ExecuteReader();
try
{
while (reader.Read())
{
result = reader[0].ToString();
}
}
catch (Exception ex)
{
result = ex.Message;
}
return result;

SELECT ##IDENTITY in Access always returning 0

I have been trying to find a solution to this problem but so far nothing worked.
private void Insert()
{
string ConnectionStringAccess = Provider=Microsoft.ACE.OLEDB.12.0;Data Source=###Jet OLEDB:Database Password=###;
string query2 = "Select ##Identity";
int id = -1;
string Query = "INSERT INTO tblTable (EmpNo, Name) VALUES (132, 'TestName');";
OleDbConnection con = new OleDbConnection(ConnectionStringAccess);
OleDbCommand cmd = new OleDbCommand(Query, con);
try
{
con.Open();
if (cmd.ExecuteNonQuery() == 1)//the insert succeded
{
cmd.CommandText = query2;
id = Convert.ToInt32(cmd.ExecuteScalar());
}
}
catch (Exception ex)
{
//log the ex
}
finally
{
con.Dispose();
con.Close();
}
}
Each time I use the above method I always get a return of 0 in "id". What am I doing wrong? I tried using a different connection string or another way to get latest identifier:
Provider=Microsoft.Jet.OLEDB.4.0;
SCOPE_IDENTITY()
but again nothing. The Access db is 2003 or older (not sure exactly).
The ms access db is 2003 or older (not sure exactly)
I was able to recreate your issue with an Access 97 database. SELECT ##IDENTITY worked correctly with an Access 2000 database file (even when run from the same OleDbCommand object as the INSERT), but it always returned zero when run against an Access 97 database.
It appears that you will need to upgrade your database file to a newer version if you want SELECT ##IDENTITY to work.
You are using the same command object for both the insert and retrieval of ##identity.
According to this article you should create a separate command object for retrieving the ##identity value:
http://support.microsoft.com/kb/815629
Also, just to verify, the table you are inserting to does have an auto increment column, is that correct? If not, ##identity would not return anything.
Create two different commands for your queries, execute non query then execute scalar. It will return the first column of the first row in the result set returned by the query and it should be the id you're looking for.
private void Insert()
{
string ConnectionStringAccess = Provider=Microsoft.ACE.OLEDB.12.0;Data Source=###Jet OLEDB:Database Password=###;
int id = -1;
string Query = "INSERT INTO tblTable (EmpNo, Name) VALUES (132, 'TestName')";
string Query2 = "SELECT ##Identity";
OleDbConnection con = new OleDbConnection(ConnectionStringAccess);
OleDbCommand cmd = new OleDbCommand(Query, con);
OleDbCommand cmd2 = new OleDbCommand(Query2, con);
try
{
con.Open();
cmd.ExecuteNonQuery();
id = (int)cmd2.ExecuteScalar();
}
catch (Exception ex)
{
//log the ex
}
finally
{
con.Dispose();
con.Close();
}
}
thanks for all the responses. I found out what the problem was. Apparently the access file is very old, 1997 to be exact and that was the problem. As soon as a tried a new access 2010 file it worked.
Thanks again
My soluce with my very older databases (VB6 and ACCESS)
With VB NET and before upgrade Database to 4.
'MyInsertCommand.CommandText = "Select ##Identity" Don't work with old Access database
MyInsertCommand.CommandText = "SELECT TOP 1 ME_idn FROM MESURE ORDER BY ME_idn Desc"
Dim MyInsertIdn As Integer = MyInsertCommand.ExecuteScalar()

SQL connection commands doesn't change the data

How can I know whether the table in database is affected after these instructions? I try to show the query result in console but it doesn't show anything.
static void Main(string[] args)
{
DateTime date = new DateTime(2013, 3, 4);
try
{
SqlConnection connection = new SqlConnection("Data Source=ExchangeRatesByDate/TestApplication/Rates_DB.sdf");
Console.WriteLine("Connection is created");
connection.Open();
Console.WriteLine("Connection is opened");
SqlCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES (USD, 1, 417.5, date)";
insertCommand.ExecuteNonQuery();
SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Rates_Table", connection);
DataTable data = new DataTable();
adapter.Fill(data);
Console.WriteLine(adapter);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
ExecuteNonQuery() returns an integer showing number of affected rows. ExecuteNonQuery
You can use the ExecuteNonQuery to perform catalog operations (for
example, querying the structure of a database or creating database
objects such as tables), or to change the data in a database without
using a DataSet by executing UPDATE, INSERT, or DELETE statements.
Although the ExecuteNonQuery returns no rows, any output parameters or
return values mapped to parameters are populated with data.
For UPDATE, INSERT, and DELETE statements, the return value is the
number of rows affected by the command. When a trigger exists on a
table being inserted or updated, the return value includes the number
of rows affected by both the insert or update operation and the number
of rows affected by the trigger or triggers. For all other types of
statements, the return value is -1. If a rollback occurs, the return
value is also -1.
try like this
int updatedRows = insertCommand.ExecuteNonQuery();
if(updatedRows>0)
{
//do something
}
i think u are showing SqlDataAdapter object show to datatable ,and also use parameter for the insert string like 'USD'
the ExecuteNonQuery() returns an integer for the number of affected records.
int _affected = insertCommand.ExecuteNonQuery();
ExecuteNonQuery()
follow-up question
INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES (USD, 1, 417.5, date)
in the statement above, are values USD and date are real values because if so, it pretty sure it will thrown an exception. It should be wrap with single quotes like this:
INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES ('USD', 1, 417.5, '')
because they are string literals. But it's not the proper way to insert data with real values in the INSERT statement. The values should be parameterized to avoid sql injection.
string sqlStatement = "INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES (#iso, #Amount, #rate, #date)";
using (SqlConnection conn = new SqlConnection(connStr))
{
using(SqlCommand comm = new SqlCommand())
{
comm.Connection = conn;
comm.CommandText = sqlStatement;
comm.CommandType = CommandType.Text;
comm.Parameters.AddWithValue("#iso", '-- value --');
comm.Parameters.AddWithValue("#Amount", '-- value --');
comm.Parameters.AddWithValue("#rate", '-- value --');
comm.Parameters.AddWithValue("#date", '-- value --');
try
{
conn.Open();
int _affected = comm.ExecuteNonQuery();
}
catch(SqlException e)
{
// do something with the exception
// do not hide it
// e.Message.ToString()
}
}
}
For proper coding
use using statement for propr object disposal
use try-catch block to properly handle objects

error with SqlCe Parameters

I have made MANY parameterised queries in my time on this lovely planet, and none have thrown an error like this... WTFudge?!?!
ERROR:
There was an error parsing the query. [
Token line number = 1,
Token line offset = 20,
Token in error = #table ]
Obviously the compiler doesn't like my SQL statement... but I see no problem???
Here is my code.
using (SqlCeConnection con = new SqlCeConnection(_connection))
{
string sqlString = "SELECT #colID FROM #table WHERE #keyCol = #key";
SqlCeCommand cmd = new SqlCeCommand(sqlString, con);
cmd.Parameters.Add(new SqlCeParameter("#table", tableName));
cmd.Parameters.Add(new SqlCeParameter("#colID", columnIdName));
cmd.Parameters.Add(new SqlCeParameter("#keyCol", keyColumnName));
cmd.Parameters.Add(new SqlCeParameter("#key", key));
try
{
con.Open();
return cmd.ExecuteScalar();
}
catch (Exception ex)
{
Console.Write(ex.Message);
throw new System.InvalidOperationException("Invalid Read. Are You Sure The Record Exists", ex);
}
finally
{
if (con.State == ConnectionState.Open)
con.Close();
cmd.Dispose();
GC.Collect();
}
}
as you can see its a VERY simple SQL statement. I though "#table" may have been stupidly reserved or something... so ive tried #tableName, #var, #everything!!! dont know what the problem is.
During debug I checked that there was actually a #table parameter in the SqlCeParameterCollection And it was there. Clear as day!!
Since you are in C# (as opposed to stored procs)
string sqlString = "SELECT " + columnIdName +
" FROM " +tableName "WHERE " + keyColumnName + "= #key";
You will want to verify that columnIdName, tableName, keyColumnName are all restricted to a list of values (or at the very least, restrict the length to, say 50 characters), otherwise this procedure is optimized for insecurity and sql injection attacks.
This affected me too on SqlCe. But in Sql Server and in SqlExpress you can use a paarameter for table name.

Categories

Resources