SQLite: Insert Into Identity Column [duplicate] - c#

This question already has answers here:
Is there AUTO INCREMENT in SQLite?
(9 answers)
Closed last month.
I'm new to SQLite and I'm trying to run the following code:
using (var cn = new SQLiteConnection("Data Source=:memory:;Version=3;")) {
cn.Open();
var cmd = cn.CreateCommand();
cmd.CommandText = "CREATE TABLE [ContentItems] ([Id] [int] IDENTITY(1,1) NOT NULL, [Title] [nvarchar](100) NOT NULL, CONSTRAINT [PK_ContentItems] PRIMARY KEY ([Id]))";
cmd.ExecuteNonQuery();
var cmd2 = cn.CreateCommand();
cmd2.CommandText = "INSERT INTO [ContentItems] (Title) VALUES ('Test 1')";
cmd2.ExecuteNonQuery();
}
But this gives the error:
Abort due to constraint violation ContentItems.Id may not be NULL
I've had a look through the documentation but based on my past SQL experience I cannot see why this doesn't work. I'd appreciate the help. Thanks

SQLite creates what you're thinking of as an IDENTITY column using the AUTOINCREMENT keyword. In your example, the ID column is not created with AUTOINCREMENT and, since it is declared NOT NULL, you must supply a value.
The CREATE statement you're after is:
CREATE TABLE [ContentItems] (
[Id] INTEGER AUTOINCREMENT NOT NULL,
[Title] TEXT NOT NULL,
CONSTRAINT [PK_ContentItems] PRIMARY KEY ([Id])
)
Note that SQLite uses the TEXT data type (although it will map anything containing "CHAR" to that datatype) and doesn't need or respect maximum field lengths.

Related

How do I get primary key of colliding row on failed insert?

After I try to insert a row into database and it fails due to duplicate (not primary key collision - another key), how do I get the primary key of the colliding row that prevented the insert?
Example:
The table:
CREATE TABLE `my_table` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`unique_value` varchar(60) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_data` (`unique_values`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Some initial data:
INSERT INTO `my_table`(`unique_value`) VALUES ('unique string 1');
INSERT INTO `my_table`(`unique_value`) VALUES ('unique string 2');
And now, this will fail because of the collision in the index:
MySqlConnection conn = new MySqlConnection(connString);
conn.Open();
MySqlCommand comm = conn.CreateCommand();
comm.CommandText = "INSERT INTO `my_table`(`unique_value`) VALUES 'unique string 2'";
comm.ExecuteNonQuery();
conn.Close();
Can I get the primary key of the colliding row without making another query?
while creating the table you can use "Identity" keyword which will do all the "not null and Auto Increment" Stuff.
But this is for MsSQL
Try this:
create table my_table
(
ID int Primary key identity,
unique_value varchar(60) NOT NULL
)
As you said this that you are not worry about PK hence you can check the value of the column which has unique index.If there is already a raw with the value that you passing in new row then you are trying to insert duplicate otherwise not.

SqliteCommand.ExecuteReader() returning no rows

I'm trying to read data from a table in my Sqlite database using the Microsoft.Data.Sqlite classes in a UWP application.
There's a single row in the table, inserted by the same application. I can see the data using a Sqlite database browser, and can copy-paste the SQL query into the database browser, run it, and see the correct result returned.
However, when I run the same query using the code below, no data is returned.
string _query = "SELECT [Source] FROM [Sessions] ORDER BY [MinTimeOffset];";
_SessionList = new List<string>();
using (SqliteCommand _command = new SqliteCommand(_query, _Connection))
{
using (SqliteDataReader _reader = _command.ExecuteReader())
{
while (_reader.Read())
{
_SessionList.Add((string)_reader["Source"]);
}
}
}
The table structure is as follows:
CREATE TABLE Sessions (
[Id] INTEGER PRIMARY KEY AUTOINCREMENT,
[Source] NVARCHAR(255) NOT NULL,
[MinValue] FLOAT NULL,
[MaxValue] FLOAT NULL,
[MinTimeOffset] BIGINT NULL,
[MaxTimeOffset] BIGINT NULL
)
And the data is:
1, "2017-09-17-070007-ELEMNT BOLT BDA2-15-0.fit", NULL, NULL, NULL, NULL
No exceptions are thrown, _reader.Read() returns false the first time it is called, and _reader.HasRows is false, suggesting no data is returned by the query.
I'm sure there's something simple I'm missing here - what could cause this?
Update following comments:
I can use ExecuteScalar() to retrieve data from the same table without a problem, although this is performed as part of a transaction alongside thousands of inserts, so I guess is slightly different. The code for that, which works, is as follows:
_query = "SELECT [Id] FROM Sessions WHERE [Source] = #sessionName LIMIT 1;";
long _sessionId;
_IngestCommand.CommandText = _query;
_IngestCommand.Parameters.Add(new SqliteParameter("#sessionName", sessionName));
_sessionId = (long)_IngestCommand.ExecuteScalar();
Regarding how I connection, the database is either a new database created from scratch via DDL statements, or an existing version created in the same manner. It makes no difference which of those two methods I use. There's only one database file at any time - I'm deleting the folder contents manually before running to be sure I'm not opening any copies or old versions etc, then creating the database programmatically and inserting a bunch of data into it in a transaction, including a record into this table which is successfully retrieved as part of the insert logic, then committing the transaction.
At this point I can browse all of the inserted data in a Sqlite database browser. Then I'm calling the method which includes the ExecuteReader() code shown above and receiving no results. The same connection is used throughout - it's opened in a class constructor and closed in the Dispose() method of that class (I know that's not great design - I'm going to refactor it once I've got this figured out. The connection code is shown below:
var _connSB = new SqliteConnectionStringBuilder
{
Cache = SqliteCacheMode.Private,
DataSource = filename,
Mode = SqliteOpenMode.ReadWriteCreate
};
_Connection = new SqliteConnection(_connSB.ToString());
_Connection.Open();
And the code that builds the database:
string[] _commands = {
"CREATE TABLE IF NOT EXISTS ProjectMetaData ([Id] INTEGER PRIMARY KEY AUTOINCREMENT, [Name] NVARCHAR(100) NOT NULL, [Value] NVARCHAR(255) NOT NULL)",
"CREATE TABLE IF NOT EXISTS Series ([Id] INTEGER PRIMARY KEY AUTOINCREMENT, [Name] NVARCHAR(100) NOT NULL, [Unit] NVARCHAR(48) NOT NULL, [MinValue] FLOAT NULL, [MaxValue] FLOAT NULL, [MinTimeOffset] BIGINT NULL, [MaxTimeOffset] BIGINT FLOAT NULL)",
"CREATE TABLE IF NOT EXISTS Sessions ([Id] INTEGER PRIMARY KEY AUTOINCREMENT, [Source] NVARCHAR(255) NOT NULL, [MinValue] FLOAT NULL, [MaxValue] FLOAT NULL, [MinTimeOffset] BIGINT NULL, [MaxTimeOffset] BIGINT NULL)",
"CREATE TABLE IF NOT EXISTS Data ([Id] INTEGER PRIMARY KEY AUTOINCREMENT, [SeriesId] INT NOT NULL, [SessionId] NOT NULL, [TimeOffset] BIGINT NOT NULL, [Value] FLOAT NOT NULL, [Discounted] BIT NULL)"
};
foreach (string _command in _commands)
{
using (SqliteCommand _dbCommand = new SqliteCommand(_command, _Connection))
{
_dbCommand.ExecuteNonQuery();
}
}

C# Two classes and two tables link

I'm doing a project and I'm stuck at the beginning already
So I got two tables for two classes like this:
CREATE TABLE [dbo].[T_Artikli] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Naziv] NVARCHAR (100) NOT NULL,
[Sifra] VARCHAR (13) NOT NULL,
[Vp] FLOAT (53) NOT NULL,
[MP] FLOAT (53) NOT NULL,
[Napomena] NVARCHAR (300) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
and
CREATE TABLE [dbo].[T_Stanje] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Trenutno] INT NOT NULL,
[Naruceno] INT NOT NULL,
[Datum] DATE NOT NULL,
[Firma] NVARCHAR (40) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_T_Stanje_T_Artikli] FOREIGN KEY ([Id]) REFERENCES [dbo].[T_Artikli] ([Id])
);
The 'Artikl' class and its table 'T_Artikli' works like a charm,the problem is with the other one. This chunk of code should store values in a table:
private void btnSacuvaj_Click(object sender, EventArgs e)
{
CStanje sta = new CStanje();
sta.Trenutno = Int32.Parse(txtTrenutno.Text);
sta.Naruceno = Int32.Parse(txtNaruceno.Text);
sta.Firma = txtFirma.Text;
sta.Datum = DateTime.Parse(dtDatum.Text);
Artikl art = new Artikl();
art.ID = Int32.Parse(cbArtikli.SelectedValue.ToString());
sta.Artikl = art;
Console.WriteLine(sta.Trenutno);
Console.WriteLine(sta.Naruceno);
Console.WriteLine(sta.Firma);
Console.WriteLine(sta.Datum);
Console.WriteLine(art.ID);
sta.dodajStanje();
indeksSelektovanog = dgStanje.Rows.Count;
}
It returns this error:
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_T_Stanje_T_Artikli". The conflict occurred in database "C:\USERS\MORSUS\DOCUMENTS\VISUAL STUDIO 2015\PROJECTS\SEMINARSKI\EVIDENCIJA\EVIDENCIJA\BIN\DEBUG\EVIDENCIJADB.MDF", table "dbo.T_Artikli", column 'Id'.
On this line:
public void dodajStanje()
{
string insertSql = "INSERT INTO T_Stanje " +
"(Trenutno, Naruceno, Datum, Firma) VALUES " +
"(#Trenutno, #Naruceno, #Datum, #Firma)";
using (SqlConnection connection = new SqlConnection(_connectionString))
{
SqlCommand command = connection.CreateCommand();
command.CommandText = insertSql;
//command.Parameters.Add(new SqlParameter("#Sifra", Sifra));
command.Parameters.Add(new SqlParameter("#Trenutno", Trenutno));
command.Parameters.Add(new SqlParameter("#Naruceno", Naruceno));
command.Parameters.Add(new SqlParameter("#Datum", Datum));
command.Parameters.Add(new SqlParameter("#Firma", Firma));
connection.Open();
command.ExecuteNonQuery(); //error
}
}
I assume I did something wrong in the sql. Can anyone point me out please?
Another question about sql, how come my sql tables are saved for some only some time, eg 3-4 program runs. The data gets wiped after some time don't know when exactly.. And Copy to Output Directory is set to Copy if Newer.
Be free to ask for any more info.
Yes, this constraint is wrong below; you have the primary key of the T_Stanji table as both the primary key and the foreign key to the T_Artikli table, which can't happen. Note both uses of the same column Id.
CONSTRAINT [FK_T_Stanje_T_Artikli] FOREIGN KEY ([Id]) REFERENCES [dbo].[T_Artikli] ([Id])
You need to add an ArtikliID to the T_Stanje table:
[ArtikliID] INT (NULL | NOT NULL)
And then change this constraint to be:
CONSTRAINT [FK_T_Stanje_T_Artikli] FOREIGN KEY ([ArtikliID]) REFERENCES [dbo].[T_Artikli] ([Id])
So that the foreign key of this new column is mapped.

insert and update sql statement in single sql statement

I want to create insert and update sql statements in single statement. But insert statement is for one table and update statement for another table...
this is Appliance_Location table
CREATE TABLE [dbo].[Appliance_Location] (
[Appliance_Id] NCHAR (10) NOT NULL,
[RoomId] NVARCHAR (20) NOT NULL,
[ApplianceName] NCHAR (10) NOT NULL,
[AddDate] DATE NULL,
CONSTRAINT [PK_Appliance_Location] PRIMARY KEY CLUSTERED ([Appliance_Id] ASC)
);
and this is Appliance_Count table
CREATE TABLE [dbo].[Appliance_Count] (
[RoomId] NVARCHAR (20) NOT NULL,`enter code here`
[Bulb] INT NOT NULL,
[Fan] INT NOT NULL,
[AC] INT NOT NULL,
[Computer] INT NOT NULL,
CONSTRAINT [PK_Appliance_Count] PRIMARY KEY CLUSTERED ([RoomId] ASC)
);
when I insert an appliance to the Appliance_Location table then count of that particular appliance in Appliance_Count table should be updated
It is not possible to insert and update in single query. But You have one option for this task. You can create trigger to inserting of one table. And trigger through update value in other table.
Not sure how about other SQL servers, but you are allowed to execute multiple queries using the same syntax in MS SQL.
using (SqlConnection connection = CreateConnection())
{
SqlCommand command = connection.CreateCommand();
command.CommandText = #"INSERT INTO `TableA` VALUES (1, 2, 3);
UPDATE `TableB` SET [Val] = 'value' WHERE [Id] > 10";
command.CommandType = CommandType.Text;
// ... other initializations
return command.ExecuteNonQuery();
}
You even can return values:
INSERT INTO `TableC` VALUES (1, 'value');
SELECT SCOPE_IDENTITY() AS Id;
After this query you can get SQL reader and read "Id" value from the response.
Why don't you just try before asking?

Insert a record in table fails everytime

I have a database connection where i insert data into the table having 2 columns i.e. id,first_name,last_name.
Following is the code:
private void Insert_Click(object sender, EventArgs e)
{
try
{
String query = "INSERT INTO data_table (first_name,last_name) VALUES (#f_name,#l_name)";
using (SqlConnection connection1 = new SqlConnection(
Properties.Settings.Default.DatabaseConnection))
using (SqlCommand insertCommand = new SqlCommand(query, connection1))
{
//a shorter syntax to adding parameters
// insertCommand.Parameters.Add("#id", SqlDbType.Int).Value = 1;
insertCommand.Parameters.Add("#f_name", SqlDbType.NChar).Value = "JAVED";
insertCommand.Parameters.Add("#l_name", SqlDbType.NChar).Value = "GHAMJN";
//make sure you open and close(after executing) the connection
connection1.Open();
insertCommand.ExecuteNonQuery();
connection1.Close();
MessageBox.Show("Record inserted. Please check your table data. :)");
}
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
}
Following is T-SQL script:
CREATE TABLE [dbo].[data_table] (
[Id] INT NOT NULL IDENTITY,
[first_name] NCHAR (10) NULL,
[last_name] NCHAR (10) NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
The issue is created by id: I have set it auto-increment.
When i click insert button a MessageBox pops saying:
Cannot insert the value NULL into column 'Id',table 'C:\Users.......\Database1.MDF.dbo.data_table;column doesn't allows null.INSERT fails
Add identity seed and increment values to your table...
CREATE TABLE [dbo].[data_table] (
[Id] INT NOT NULL IDENTITY(1,1),
[first_name] NCHAR (10) NULL,
[last_name] NCHAR (10) NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
Your Id field should be modified as shown below
Deleting that table alongwith all the old copies of old table and creating a new table with suggested Identity(1,1) resolved the issue
try this. The behaviour of Identity Columns can be selectively enabled or disabled with this statement.
If your Identity Column is configured correctly, then this is the only logical explanation for it not behaving as expected
SET IDENTITY_INSERT [dbo].[data_table] ON;
However, it is more likely that your assertion of correctness is flawed and you have not configured the Identity Column correctly.

Categories