I need help because I cannot understand what I'm doing wrong here.
Initial setup:
MS Access database (.mdb).
MS Office 2010 installed.
MS SQL Server 2008
I built the routine to sync records from MS SQL Server 2008 to MS Access database. Tables are identical when it comes to table layout and number of fields
The part of the routine there is an INSERT SQL statement
and part of SQL statement this code
//Query to execute
cmdToExecute.CommandText = "INSERT INTO " + tableName +
"(EquipmentID, TimeInspected) VALUES(" +
"'" + this._strEquipmentId.ToString() + "'," +
"'" + this._dtTimeInspected.Value.ToString("yyyy-MM-dd hh:mm:ss tt") + "'";
_stTimeInspected is declared as sqlDateTime.
For some reason I cannot get Date and Time together in MS Access database table.
When I use the format like this._dtTimeInspected.Value.ToString("yyyy-MM-dd") I can get date, or
this._dtTimeInspected.Value.ToString("hh:mm:ss tt") I can get Time
but for some reason time is being truncated when I use this: _dtTimeInspected.Value.ToString("yyyy-MM-dd hh:mm:ss tt")
I even try to use parametrized query
PARAMETERS [#EquipmentID] Text ( 255 ), [#TimeInspected] DateTime;
INSERT INTO VisualInspectionHistory ( EquipmentID, , DateInspected, TimeInspected, RecordIsUpdated, DateSync, TimeSync )
SELECT [#EquipmentID] AS Expr1, [#TimeInspected] AS Expr2
/// <summary>
/// Purpose: Insert new record into database table
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
public override bool Insert()
{
OleDbCommand cmdToExecute = new OleDbCommand();
cmdToExecute.CommandText = "VisualInspection_Insert";
cmdToExecute.CommandType = CommandType.StoredProcedure;
cmdToExecute.Connection = conMainConnection;
try
{
cmdToExecute.Parameters.Add(new OleDbParameter("#EquipmentID", (OleDbType)OleDbType.VarChar, 25)).Value = _strEquipmentID.ToString();
cmdToExecute.Parameters.Add(new OleDbParameter("#TimeInspected", (OleDbType)OleDbType.Date)).Value = (DateTime)(_dtTimeInspected);
if (bMainConnectionIsCreatedLocal)
{
//Open connction
conMainConnection.Open();
}
else
{
if (cpMainConnectionProvider.IsTransactionPending)
{
cmdToExecute.Transaction = cpMainConnectionProvider.CurrentTransaction;
}
}
//Execute query
iRowsAffected = cmdToExecute.ExecuteNonQuery();
return true;
}
catch (OleDbException ex)
{
//Some error occured. Bubble it to caller and encapsulate Exception object
throw ex;
}
catch (Exception ex)
{
//Some error occured. Bubble it to caller and encapsulate Exception object
throw ex;
}
finally
{
if (bMainConnectionIsCreatedLocal == true)
{
//Close connection
conMainConnection.Close();
}
cmdToExecute.Dispose();
}
}
Any help would be greatly appreciated.
I found the solution.
To insert Date and time
//Query to execute
cmdToExecute.CommandText = "INSERT INTO " + tableName +
"(EquipmentID, TimeInspected) VALUES(" +
"'" + this._strEquipmentId.ToString() + "'," +
"#" + this._dtTimeInspected.Value.ToString("yyyy/MM/dd hh:mm:ss tt") + "#";
even without parametrized procedures
To insert time
`//Query to execute
cmdToExecute.CommandText = "INSERT INTO " + tableName +
"(EquipmentID, TimeInspected) VALUES(" +
"'" + this._strEquipmentId.ToString() + "'," +
"#" + this._dtTimeInspected.Value.ToString("hh:mm:ss tt") + "#";`
Thank you for your help
Related
I have a support tool I have written that allows me to create a table in MS Access DB file. Because of the support, I set it so it just creates the table without any columns defined. There is another part of the same program which allows column creations. However when I select the table in my list, I try to load the table. Since the table is empty, the system throws an error at the Fill (I understand the Select is the cause). Is there a way to ask if a table has any columns before trying to load that table?
public static bool ConnectToDatabase(string dbTable)
{
return ConnectToDatabaseWStr(dbTable, "Select * From `" + dbTable + "`");
}
public static bool ConnectToDatabaseWStr(string dbTable, string strSQL)
{
try
{
conn = new OleDbConnection(connectionString);
}
catch (Exception e)
{
LogFile.write(1, "DataAccess: error detected when creating OLEDBConnection.\nConnection string:\n" + connectionString + "\n" + e.ToString() + "\n");
}
try
{
dataAdapter = new OleDbDataAdapter(strSQL, conn);
dataAdapter.Fill(DataSetList[iCurrDataSetListIndex].DataSetInstance, dbTable);
This is easy if there are columns.
You can even go SELECT * from tableName where ID = 0
And then for each the column names. However, while the above will return 0 rows, the columns still do come through. However, without ANY columns, then the above will fail, and you would in theory have to know the "ID" column existed.
You can thus get oleDB provider to return a table as a "schema". This is table of ROWS of the defined table. Thus you can use this:
If NO rows are returned, then we don't have a table that lays out and defines the schema:
var strTableName = "tblHotels";
OleDbConnection myCon = new OleDbConnection(My.Settings.TestDB);
myCon.Open();
string[] SchemaParams = new[] { null, null, strTableName, null };
DataTable MyTable = myCon.GetSchema("Columns", SchemaParams);
if (MyTable.Rows.Count == 0)
// no columns for table
Debug.Print("no columns in table");
else
foreach (DataRow MyRow in MyTable.Rows)
Debug.Print(MyRow("Column_Name") + "->" + MyRow("Data_Type"));
i have this code here:
var sql = "select shr_id, shc_id " +
"from tbox_operational.shipment_ref " +
"inner join tbox_operational.shipment_collo_ref using (shr_id) " +
"where shr_insdtm between ?dateTimeFrom";
var parameters = new List<MySqlParameter> {
new MySqlParameter("?dateTimeFrom", dateTimeFrom.ToString("yyyy/MM/dd HH:mm:ss"))
};
var query = (from db in context.Database.SqlQuery<ShridsModel>(sql, parameters)
select db).ToList();
return query;
But it keeps me getting this error:
{"Parameter '?dateTimeFrom' must be defined."}
i have also in my connection string:
server=xxx;user id=runtime;password=xxxx;AllowUserVariables=True;
What am i doing wrong here?
I have solved...
Instead of passing a list of the parameters, i pass each one individual and he recognizes it all
I have a big data array which I try to insert into my database, then delete an old table and rename the new one. To do it faster I use TRANSACTION (it doesn't affect my problem, I tried without it) and make every MySQL query inside async.each function. In the callback of this async.each I do COMMIT (for transaction), deleting and renaming.
Usually I have 100000 or more rows to insert. If I use "SELECT COUNT(*)" in terminal I can see these rows insert quite slowly but somehow the process ends immediately when 1/4 of rows was inserted. Then I got a full table in one moment. I don't know why it happens, I'm OK with that but maybe this is the reason of my problem.
So this is my problem: I have no access to DB from Node while it makes inserting. But I still can access it from terminal where I can count rows, see a tables etc. If Node calls some other function with mysql query, this query will just wait until that big insert will end.
It's like Node code works in parallel but mysql queries work in just one thread. How can I fix this?
exports.insertSubscribers = function(data, db_name, done){
state.pool.query('START TRANSACTION');
async.each(data, function(row, cb){
state.pool.query('INSERT INTO new_' + db_name + ' (id, first_name, last_name, sex, city, country, photo_200) VALUES (' + "'" + row.id + "', " + "'" + row.first_name + "', " + "'" + row.last_name + "', " + "'" + row.sex + "', " + "'" + JSON.stringify(row.city) + "', " + "'" + JSON.stringify(row.country) + "', " + "'" + row.photo_200 + "'" + ')', cb);
}, end_transaction);
function end_transaction(){
state.pool.query('COMMIT', function(err){
if(err) return done(err);
state.pool.query('SHOW TABLES LIKE \'' + db_name + '\'', function(err, result){
if(result.length != 0){
state.pool.query('DROP TABLE ' + db_name, function(err){
if(err) return done(err);
state.pool.query('RENAME TABLE new_' + db_name + ' TO ' + db_name, function(err){
if(err) return done(err);
});
});
}else{
state.pool.query('RENAME TABLE new_' + db_name + ' TO ' + db_name, function(err){
if(err) return done(err);
});
}
});
});
}
};
MySQL by design only allows at most one query per connection at any given time. So what some MySQL drivers/modules do is to simply maintain an in-memory queue that is used when additional queries are made while another is in progress.
One possible workaround for this is to use multiple connections in a pool (the mysql and mysql2 modules have built-in pooling support for example) so that you can execute more queries in parallel.
Im trying to do this:
String insertQuery=" DELETE FROM Accounts WHERE Username= " + Username + ";";
But im getting this error:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'sam' in 'where clause'
Its getting the right username etc I know this by testing, I assume the syntax is wrong but im getting no syntax errors?
The table is called Accounts. The coloums are Username & Password,
You are missing single quotes. In your case(it's string) variable need to be wrapped in them or it'll be interpreted as column.
String insertQuery = "DELETE FROM Accounts WHERE Username = '" + Username + "'";
Recommendation:
Hence i recommend you to use placeholders to avoid this kind of problem. Don't forget to care about a security(SQL Injection for instance). It's worth to say that parametrized statements are also more human-readable, safer and faster as well.
I don't like "hardcoded" queries. Let's imagine a scenario if you had a table with ten columns and imagine how you query will look in this case: absolutely human-unreadable.
An usage of parametrized statements is always very efficient and comfortable practise. Your code looks good and becomes human-readable and what is "main" solution is much more safer and cleaner.
Have look at PreparedStatements. Basic example:
private final String deleteQuery = "DELETE FROM Accounts WHERE Username = ?";
public boolean deleteObject(String username) {
Connection c = null;
PreparedStatement ps = null;
try {
c = DataSource.getConnection();
ps = c.prepareStatement(deleteQuery);
ps.setString(1, username); // numbering starts with 1 not 0!
return ps.executeUpdate() > 0;
}
catch (SQLException ex) {
System.out.println("Error in deleteObject() method: " + ex.getMessage());
return false;
}
finally {
if (c != null) {
try {
c.close();
}
catch (SQLException ex) {
System.out.println("Error in closing conn: " + ex.getMessage());
}
}
}
}
If username is a varchar you need to add single quotes around the value in the where clause.
String insertQuery=" DELETE FROM Accounts WHERE Username= '" + Username + "';";
Since the value is not quoted its identifying the username, I'm assuming its Sam as a column.
I am trying to prevent SQL injection in my Java program. I want to use PreparedStatements to do this, but I don't know the number of columns or their names in advance (the program allows administrators to add and remove columns from the tables). I'm new to this, so this may be a silly question, but I'm wondering if this approach is safe:
public static int executeInsert( String table, Vector<String> values)
{
Connection con;
try {
con = connect();
// Construct INSERT statement
int numCols = values.size();
String selectStatement = "INSERT INTO " + table + " VALUES (?";
for (int i=1; i<numCols; i++) {
selectStatement += ", ?";
}
selectStatement += ")";
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
// Set the parameters for the statement
for (int j=0; j<numCols; j++) {
prepStmt.setString(j, values.get(j));
}
System.out.println( "SQL: " + prepStmt) ;
int result = prepStmt.executeUpdate();
con.close() ;
return( result) ;
} catch (SQLException e) {
System.err.println( "SQL EXCEPTION" ) ;
System.err.println( "Inserting values " + values + " into " + table);
e.printStackTrace();
}
return -1;
}
Basically I'm creating the String for the statement dynamically based on how many values are passed in (and therefore how many columns are in the table). I feel like it's safe because the PreparedStatement is not actually created until after this string is made. I may make similar functions that take in actual column names and incorporate them into the SQL statement, but these will be produced by my program and not based on user input.
Any time you have values like table being inserted into your query without escaping, you should test against a whitelist of known-good values. This prevents people from being creative and causing trouble. A simple dictionary or array of valid entries usually suffices.
Using a prepared statement is a good idea, but be sure the statement you're preparing doesn't allow for injections right from the start.