I am trying to insert "0000.0000.0000.0001" into a varchar(50) in my sql database in c#. I keep getting this error:
There was an error parsing the query. [ Token line number = 1,Token line offset = 122,Token in error = .0000 ]
How my insertion looks like is:
string version = "0000.0000.0000.0001";
INSERT INTO [DBFileInfo] (DBFileInfoID,DatabaseType,Version, Description, CreationDate,ReleaseDate)
values(1,1,"+version.ToString()+
",`Default Beverage DB created by DbGen`,
CURRENT_TIMESTAMP,CURRENT_TIMESTAMP)";
The initial build of the table is:
string info = " CREATE TABLE [DBFileInfo]( [DBFileInfoID] INT NOT NULL,[DatabaseType] INT NOT NULL DEFAULT(-1),[Version] VARCHAR(50) NOT NULL, [Description] NVARCHAR(256) NOT NULL, [CreationDate] DATETIME,[ReleaseDate] DATETIME);";
is there a way around this so I could insert the "." into it without getting an exception?
THanks!
You need to put the string inside single quotes:
string version = "0000.0000.0000.0001";
...values(1,1,'" + version + "','...
HOWEVER
I strongly recommend you use parameters instead. e.g.
string version = "0000.0000.0000.0001";
string sql = #"INSERT INTO [DBFileInfo] (DBFileInfoID,DatabaseType,Version, Description, CreationDate,ReleaseDate)
VALUES(1,1,#Version,'Default Beverage DB created by DbGen',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);";
using (var connection = new SqlConnection(yourConnectionString))
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("#Version", version);
connection.Open();
command.ExecuteNonQuery();
}
Probably you missed quotation marks, try:
... values(1,1,'"+version.ToString()+"','Default Beverage ..
Though you might be using parameter
... values(1,1,#version,'Default Beverage ..
in this case you will have to execute your statement with parameter #version and pass value to it.
Related
I'm receiving this error '{"SQLite error\r\nnear \"Values\": syntax error"}'.
with the following block of code.
using (SQLiteConnection connection = new SQLiteConnection())
{
connection.ConnectionString = ConnectionString;
connection.Open();
using (SQLiteCommand insertSQL = new SQLiteCommand(connection))
{
insertSQL.CommandText = "INSERT INTO BetaValues(Name, Values) VALUES(#param1, #param2)";
//insertSQL.CommandType = CommandType.Text;
insertSQL.Parameters.Add("#param1", DbType.String).Value = beta.Name.ToString();
insertSQL.Parameters.Add("#param2", DbType.String).Value = beta.ValuesXML.ToString();
insertSQL.ExecuteNonQuery();
}
The data definition of my table is the following.
CREATE TABLE BetaValues (
idBetaValues INTEGER PRIMARY KEY,
Name STRING (20) NOT NULL
UNIQUE,
[Values] TEXT UNIQUE
);
I've been trying to wrap my head around this error, but I can't find the reason why I'm receiving the previous error.
Since VALUES is a SQL operator you need to use a delimited identifier to identify the column correctly. In SQLite you could to add square brackets [ColumnName] around the column name. Note that there are also other quotes possible. Have a look at the create query you've already written and modify your insert statement like
INSERT INTO BetaValues(Name, [Values]) VALUES(#param1, #param2)
to solve your problem.
I'm stuck with a problem. I'm developing a ASP.net MVC application that manages file uploads to a DB. Not that big of a deal. But every time I execute my SQL-Command, he tells me that I need to convert to VARBINARY first.
That problem is asked a lot here and on the Internet, but I still can't get it working..
That's what I got:
The SQL table:
DocID INT IDENTITY(1,1) NOT NULL,
DocName VARCHAR(512) NOT NULL,
DocData VARBINARY(max) NOT NULL,
ContentType NVARCHAR(100) NOT NULL,
ContentLength BIGINT NOT NULL,
InsertionDate DATETIME NOT NULL DEFAULT GETDATE(),
CONSTRAINT PK_DOC_STORE PRIMARY KEY NONCLUSTERED (DocID)
Read the file to a byte[] with BinaryReader.
var reader = new BinaryReader(file.InputStream);
var data = reader.ReadBytes(file.ContentLength);
And the INSERT INTO C# code:
sqlConnection.Open();
var sqlCommand = new SqlCommand
(
"INSERT INTO DocStore VALUES ('#DocumentName', '#DocumentData', '#DocumentType', '#DocumentSize', '#DocumentDate')"
, sqlConnection
);
sqlCommand.Parameters.AddWithValue("#DocumentName", file.FileName);
sqlCommand.Parameters.AddWithValue("#DocumentData", data);
sqlCommand.Parameters.AddWithValue("#DocumentType", file.ContentType);
sqlCommand.Parameters.AddWithValue("#DocumentSize", file.ContentLength);
sqlCommand.Parameters.AddWithValue("#DocumentDate", DateTime.Now);
var success = sqlCommand.ExecuteNonQuery();
sqlConnection.Close();
What's wrong here? I can't see the problem.. Shouldn't the byte[] work in a parameterized command string like this for the VARBINARY part?
You put quotes around parameter names, which will make them string literals.
Also, I would suggest to specify the columns in the insert statement. If you don't specify the columns to insert on, it takes the exact definition from your table (excluding the ID field since it is auto incremented). It is possible to break your query if you insert a field in between.
INSERT INTO DocStore (DocName, DocData, ContentType, ContentLength, InsertionDate)
VALUES (#DocumentName, #DocumentData, #DocumentType, #DocumentSize, #DocumentDate)
Solution
Instead of
var sqlCommand = new SqlCommand
(
"INSERT INTO DocStore VALUES ('#DocumentName', '#DocumentData', '#DocumentType', '#DocumentSize', '#DocumentDate')"
, sqlConnection
);
I would use
var sqlCommand = new SqlCommand
(
"INSERT INTO DocStore VALUES (#DocumentName, #DocumentData, #DocumentType, #DocumentSize, #DocumentDate)"
, sqlConnection
);
Why ?
Because "INSERT INTO ... '#DocumentData' ... " string contain a T-SQL statement. Within T-SQL, single quotes ('bla') are used to delimit the start and the end of string constant and also, in some cases, it can be used for column delimiters. So '#DocumentData' represents a string / VARCHAR constant from the point of view of SQL Server. In this case, it tries to do an implicit conversion of VARCHAR values ('#D...') to VARBINARY (data type of DocData colum; first column is skipped because it has IDENTITY property). But according to
between VARCHAR and VARBINARY are allowed only explicit conversions.
Note: as a best practice I would explicit define the list of target columns for INSERT statement.
Is there a way to retrieve the latest inserted guid in access with C#?
I tried this: Created a table Cars with a field Id of type autonumber, replicationID and a field Name varchar(250).
var command = myConnection.CreateCommand();
command.Connection.Open();
command.CommandText = "INSERT INTO Cars(Name) VALUES ('Pagani')";
command.ExecuteNonQuery();
command = context.Database.Connection.CreateCommand();
command.CommandText = "SELECT ##Identity";
Console.WriteLine(command.ExecuteScalar());
command.Connection.Close();
The issue which I am getting is:
Console.WriteLine(command.ExecuteScalar());
always shows 0
EDIT
To create the table you can use this statement over the C# OleDb connection (I think that from MS Access query does not work)
CREATE TABLE [Cars] (
[Id] guid not null DEFAULT GenGUID(),
[Name] text null
);
ALTER TABLE [Cars] ADD CONSTRAINT [PK_Cars_6515ede4] PRIMARY KEY ([Id])
I know this is not exactly what you are asking for, but let me suggest an alternative solution which might solve your underlying problem.
Create the GUID in C# and pass it to your insert:
var newGuid = Guid.NewGuid();
var command = myConnection.CreateCommand();
command.Connection.Open();
command.CommandText = "INSERT INTO Cars(Id, Name) VALUES (?, 'Pagani')";
command.Parameters.AddWithValue("#Id", newGuid); // Note: OleDb ignores the parameter name.
command.ExecuteNonQuery();
Console.WriteLine(newGuid);
GUIDs are unique. It really doesn't matter whether it is generated by your application or by the Access database driver.
This option is in all respects superior to reading the GUID afterwards:
You only need one database access.
It's less code.
It's easier.
And you can still omit the GUID in your INSERT in cases where you don't need to know the GUID - no need to change existing code.
If SELECT ##IDENTITY does not work for "ReplicationID" AutoNumber fields then the most likely way to retrieve such a value for a new record is to use an Access DAO Recordset insert, like this:
// required COM reference:
// Microsoft Office 14.0 Access Database Engine Object Library
var dbe = new Microsoft.Office.Interop.Access.Dao.DBEngine();
Microsoft.Office.Interop.Access.Dao.Database db = dbe.OpenDatabase(
#"C:\Users\Public\Database1.accdb");
Microsoft.Office.Interop.Access.Dao.Recordset rst = db.OpenRecordset(
"SELECT [Id], [Name] FROM [Cars] WHERE FALSE",
Microsoft.Office.Interop.Access.Dao.RecordsetTypeEnum.dbOpenDynaset);
rst.AddNew();
// new records are immediately assigned an AutoNumber value ...
string newReplId = rst.Fields["Id"].Value; // ... so retrieve it
// the returned string is of the form
// {guid {1D741E80-6847-4CB2-9D96-35F460AEFB19}}
// so remove the leading and trailing decorators
newReplId = newReplId.Substring(7, newReplId.Length - 9);
// add other field values as needed
rst.Fields["Name"].Value = "Pagani";
// commit the new record
rst.Update();
db.Close();
Console.WriteLine("New record added with [Id] = {0}", newReplId);
which produces
New record added with [Id] = 1D741E80-6847-4CB2-9D96-35F460AEFB19
You can try like this using the OUTPUT :
INSERT INTO myTable(myGUID)
OUTPUT INSERTED.myGUID
VALUES(GenGUID())
You can try like this:
string str1 = "INSERT INTO Cars(Name) VALUES ('Pagani')";
string str2 = "Select ##Identity";
int ID;
using (OleDbConnection conn = new OleDbConnection(connect))
{
using (OleDbCommand cmd = new OleDbCommand(str1, conn))
{
conn.Open();
cmd.ExecuteNonQuery();
cmd.CommandText = str2;
ID = (int)cmd.ExecuteScalar();
}
}
I wrote an little app in C# to keep track of customers and jobs but I get an error
"There was an error parsing the query.[Token line number = 1, Token
line offset = 14,Token in error = ']
I'm using a SQL Server CE .sdf database
public static void CreateEmployeeTable(string name)
{
conn.Open();
using (SqlCeCommand cmd = conn.CreateCommand())
{
cmd.CommandText = #"CREATE TABLE `#Name` (
`Id` INT(10) NOT NULL AUTO_INCREMENT,
`Job` VARCHAR(50) NULL,
`Pay` VARCHAR(50) NULL,
`TotalJobs` VARCHAR(50) NULL,
`TotalPay` VARCHAR(50) NULL,
PRIMARY KEY (`Id`)";
cmd.Parameters.AddWithValue("#Name", name);
cmd.ExecuteNonQuery();
}
}
I researched the error a lot and seems this error is pretty vague
You cannot parameterise a CREATE table statement that way.
Simply construct the CommandText string in code using string concatenation (being careful of possible SQL Injection vulnerabilities) and execute it.
You cannot parameterize the table name in your example. I altered your create table SQL to conform to supported data types for SQL CE. Please note that the NVARCHAR statements are set to a length of 100 to support up to the 50 characters you were specifying (VARCHAR is not supported).
I tested this code sample, but there are a couple more things to think about:
Your method is currently public. I don't know the context in which you are calling this, but consider making it private or internal.
Consider querying first to determine whether the table already exists to avoid an exception.
If at all possible I would create the connection in a using block directly above your command creation. That way you will know the connection gets closed and disposed. I'll leave that to your discretion.
public static void CreateEmployeeTable(string name)
{
const string createTableFormat = #"CREATE TABLE [{0}] (
Id INT IDENTITY NOT NULL PRIMARY KEY,
Job NVARCHAR(100) NULL,
Pay NVARCHAR(100) NULL,
TotalJobs NVARCHAR(100) NULL,
TotalPay NVARCHAR(100) NULL)";
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
// Just replace with your connection string.
using (SqlCeConnection cn = new SqlCeConnection(Settings.Default.LocalDbConnectionString))
using (SqlCeCommand cmd = cn.CreateCommand())
{
cmd.CommandText = string.Format(createTableFormat, name);
cn.Open();
cmd.ExecuteNonQuery()
}
}
I have a simple problem with a not so simple solution... I am currently inserting some data into a database like this:
kompenzacijeDataSet.KompenzacijeRow kompenzacija = kompenzacijeDataSet.Kompenzacije.NewKompenzacijeRow();
kompenzacija.Datum = DateTime.Now;
kompenzacija.PodjetjeID = stranka.id;
kompenzacija.Znesek = Decimal.Parse(tbZnesek.Text);
kompenzacijeDataSet.Kompenzacije.Rows.Add(kompenzacija);
kompenzacijeDataSetTableAdapters.KompenzacijeTableAdapter kompTA = new kompenzacijeDataSetTableAdapters.KompenzacijeTableAdapter();
kompTA.Update(this.kompenzacijeDataSet.Kompenzacije);
this.currentKompenzacijaID = LastInsertID(kompTA.Connection);
The last line is important. Why do I supply a connection? Well there is a SQLite function called last_insert_rowid() that you can call and get the last insert ID. Problem is it is bound to a connection and .NET seems to be reopening and closing connections for every dataset operation. I thought getting the connection from a table adapter would change things. But it doesn't.
Would anyone know how to solve this? Maybe where to get a constant connection from? Or maybe something more elegant?
Thank you.
EDIT:
This is also a problem with transactions, I would need the same connection if I would want to use transactions, so that is also a problem...
Using C# (.net 4.0) with SQLite, the SQLiteConnection class has a property LastInsertRowId that equals the Primary Integer Key of the most recently inserted (or updated) element.
The rowID is returned if the table doesn't have a primary integer key (in this case the rowID is column is automatically created).
See https://www.sqlite.org/c3ref/last_insert_rowid.html for more.
As for wrapping multiple commands in a single transaction, any commands entered after the transaction begins and before it is committed are part of one transaction.
long rowID;
using (SQLiteConnection con = new SQLiteConnection([datasource])
{
SQLiteTransaction transaction = null;
transaction = con.BeginTransaction();
... [execute insert statement]
rowID = con.LastInsertRowId;
transaction.Commit()
}
select last_insert_rowid();
And you will need to execute it as a scalar query.
string sql = #"select last_insert_rowid()";
long lastId = (long)command.ExecuteScalar(sql); // Need to type-cast since `ExecuteScalar` returns an object.
last_insert_rowid() is part of the solution. It returns a row number, not the actual ID.
cmd = CNN.CreateCommand();
cmd.CommandText = "SELECT last_insert_rowid()";
object i = cmd.ExecuteScalar();
cmd.CommandText = "SELECT " + ID_Name + " FROM " + TableName + " WHERE rowid=" + i.ToString();
i = cmd.ExecuteScalar();
I'm using Microsoft.Data.Sqlite package and I do not see a LastInsertRowId property. But you don't have to create a second trip to database to get the last id. Instead, combine both sql statements into a single string.
string sql = #"
insert into MyTable values (null, #name);
select last_insert_rowid();";
using (var cmd = conn.CreateCommand()) {
cmd.CommandText = sql;
cmd.Parameters.Add("#name", SqliteType.Text).Value = "John";
int lastId = Convert.ToInt32(cmd.ExecuteScalar());
}
There seems to be answers to both Microsoft's reference and SQLite's reference and that is the reason some people are getting LastInsertRowId property to work and others aren't.
Personally I don't use an PK as it's just an alias for the rowid column. Using the rowid is around twice as fast as one that you create. If I have a TEXT column for a PK I still use rowid and just make the text column unique. (for SQLite 3 only. You need your own for v1 & v2 as vacuum will alter rowid numbers)
That said, the way to get the information from a record in the last insert is the code below. Since the function does a left join to itself I LIMIT it to 1 just for speed, even if you don't there will only be 1 record from the main SELECT statement.
SELECT my_primary_key_column FROM my_table
WHERE rowid in (SELECT last_insert_rowid() LIMIT 1);
The SQLiteConnection object has a property for that, so there is not need for additional query.
After INSERT you just my use LastInsertRowId property of your SQLiteConnection object that was used for INSERT command.
Type of LastInsertRowId property is Int64.
Off course, as you already now, for auto increment to work the primary key on table must be set to be AUTOINCREMENT field, which is another topic.
database = new SQLiteConnection(databasePath);
public int GetLastInsertId()
{
return (int)SQLite3.LastInsertRowid(database.Handle);
}
# How about just running 2x SQL statements together using Execute Scalar?
# Person is a object that has an Id and Name property
var connString = LoadConnectionString(); // get connection string
using (var conn = new SQLiteConnection(connString)) // connect to sqlite
{
// insert new record and get Id of inserted record
var sql = #"INSERT INTO People (Name) VALUES (#Name);
SELECT Id FROM People
ORDER BY Id DESC";
var lastId = conn.ExecuteScalar(sql, person);
}
In EF Core 5 you can get ID in the object itself without using any "last inserted".
For example:
var r = new SomeData() { Name = "New Row", ...};
dbContext.Add(r);
dbContext.SaveChanges();
Console.WriteLine(r.ID);
you would get new ID without thinking of using correct connection or thread-safety etc.
If you're using the Microsoft.Data.Sqlite package, it doesn't include a LastInsertRowId property in the SqliteConnection class, but you can still call the last_insert_rowid function by using the underlying SQLitePCL library. Here's an extension method:
using Microsoft.Data.Sqlite;
using SQLitePCL;
public static long GetLastInsertRowId(this SqliteConnection connection)
{
var handle = connection.Handle ?? throw new NullReferenceException("The connection is not open.");
return raw.sqlite3_last_insert_rowid(handle);
}