Create table with auto increment - sqlite

I have to create a table with autoincrement column. I am creating an web app with sqlite as a background and sql alchemy is the orm layer.Python and Flask as front end. I am creating some department list and department id should be auto incremented.When I try to add department through UI I dont provide department id.Because department id is the primary key and should be auto incremented.I have added the department name and department jobs through UI without any error.But when I try to list the departments list I am getting error.
AttributeError: 'NoneType' object has no attribute 'department_id'
What I tried is,My sqlite
create table Departments(department_id primarykey integer autoincrement,department_name char,department_jobs char);
When I try creating this schema I am getting an error called 'syntax error near autoincrement'
I tried by using capital letter,auto_increment,auto increment.
Nothing is working
My sql alchemy looks like this
class Departments(db.Model):
"Adding the department"
department_id = db.Column(db.Integer,primary_key=True)
department_name = db.Column(db.String(50),nullable=False)
department_jobs = db.Column(db.String(40),nullable=False)
What I am expecting here is how do I do the auto incrementin sqllite and sqlalchemy so that I can use it in both frontend and backend.

You have coded PRIMARYKEY instead of PRIMARY KEY and you should also code INTEGER PRIMARY KEY as the column type should appear first.
There is no need, from your explanation, to code AUTOINCREMENT.
Not using AUTOINCREMENT will be more efficient and will as far as you are concerned do the same thing. i.e. if the value for the department_id is not supplied, then SQLite will automatically generate a value which will be 1 for the first row that is inserted and then typically 1 greater for the next row and so on (SQLite does not guarantee montonically increasing numbers).
SQLite Autoincrement which includes
The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and disk I/O overhead and should be avoided if not strictly needed. It is usually not needed.
I'd sugggest just using :-
create table Departments(department_id INTEGER PRIMARY KEY,department_name char,department_jobs char);

Related

sqlite3 vacuum command and referenced rowid

suppose I have a database like:
CREATE TABLE top_table (
test_id PRIMARY KEY,
cmd TEXT);
CREATE TABLE job_table (
id PRIMARY KEY,
rid integer references top_table(rowid));
If I do a vacuum, would it preserve the relationship "rid integer references top_table(rowid)"? Meaning, would it either leave the top_table rowids unchanged, or would it change them and make corresponding changes to rid in job_table? I want to do the vacuum because I'm merging databases, so I read in a second table, insert its data into an existing table, and drop the second table. If the vacuum won't work properly, my next thought was to create the combined database, drop the table, do a sump and read the sql into a new database. Or is there an easier/cleaner method that I'm unaware of?
Using :-
CREATE TABLE top_table ( test_id PRIMARY KEY, cmd TEXT);
CREATE TABLE job_table ( id PRIMARY KEY, rid integer references top_table(rowid));
Could be an issue as you are referencing the rowid directly rather than referencing an alias of the rowid. Typically an alias of the rowid would be used as per :-
CREATE TABLE top_table ( test_id INTEGER PRIMARY KEY, cmd TEXT);
CREATE TABLE job_table ( id INTEGER PRIMARY KEY, rid INTEGER REFERENCES top_table(test_id));
That is specifying INTEGER PRIMARY KEY, instead of PRIMARY KEY (column affinity NUMERIC) is a special case which makes the column being defined an alias of the rowid, the rowid will then not be subject to change by the VACUUM command as per :-
The VACUUM command may change the ROWIDs of entries in any tables that do not have an explicit INTEGER PRIMARY KEY.
SQLITE -CREATE TABLE - ROWID's and the INTEGER PRIMARY KEY
SQLite - VACUUM
I'm somewhat new at this, but strictly speaking, am I using foreign keys? I'm not declaring it to be a foreign key, and "pragma foreign_keys" returns 0
No BUT only because Foreign KEY enforcement is off (hasn't been turned on), thus the REFERENCES top_table(test_id) has no effect, other than being parsed.
Assuming that you programmatically maintain the referential integrity this should not be an issue.
It can be advantageous to have FOREIGN KEY support on as not only will referential integrity be enforced, the ON UPDATE and ON DELETE actions can then be utilised which can simplify handling updates and deletions by using the CASCADE option (e.g. deleting a parent will a) work without a conflict and b) cascade the deletion so that the children rows will be deleted automatically (if they can be))
SQLite - Enabling Foreign Key Support
SQLite - ON DELETE and ON UPDATE Actions
regarding the comment
test_id is a string, which can be relatively long (60-80 characters or so). the original version of the schema had test_id as a member of both tables. the version that I've shown above (with a bunch of fields removed from both tables for this question) was a check on how much smaller the database got if I switched matching long text strings to matching the rowid which seemed to make more sense than adding a field that serves the same purpose)
In the case where a string is used for referencing will not only save space (in the longer term) BUT the overheads will also be greater than using an alias of the rowid.
In the longer term, because SQLite save chunks (pages). A table will (by default) takes up at least 4k and then 8k ....
First, space wise, not only will the extra 52-80 bytes waste space the parent's column should also be unique. If UNIQUE were specified then there is the additional overhead of an index.
However, with an alias of the rowid, then 8 bytes max for the integer, which is used anyway unless the table is defined using WITHOUT ROWID. If I recall there is an extra byte for the flag that the column is an alias of the rowid. The rowid and therefore alias has to be unique and the index (as such) exists. Furthermore due to it being central to SQLite accessing by rowid can be twice as fast.
In short an alias of the rowid is probably the best option in many (probably most) cases for relationships.

Trying to auto-increment in Oracle 11g

I am trying to create an auto-incrementing primary key for a table but Im having no luck. This is in Oracle 11g and I am seriously missing the MySQL auto-increment command. PrimkeyID is the column I am trying to use as the primary key. This is a intersect table for a many to many relationship. At any rate, the error says that I am missing a key word just within the beginning of the primary key parenthesis. Also I don't have the privilege level required to do triggers, which appear to be important for incrementing in Oracle.
create table SITE_JUNC
(
primkeyID number,
FKsuperpave varchar(30),
FKcont_mix varchar(30),
)
;
alter table site_junc
add constraint primary key(create sequence primkeyID incement by 1),
add constraint FKsuperpave foreign key(mix_id_superpave)
references SMGR_CONT_MIX(ContMix),
add constraint FKcont_mix foreign key(mix_id_cont_mix)
references SUPERPAVE(SuperMix)
First, sequences are objects disassociated from the table.
You have to first create the sequence, and THEN the table (not necessarily in that order).
Create sequence seq_table;
Then, at the insert statement, use the seq_table.nextval (or by using triggers).
If you don't like this solution, you can use GUID (i personally don't like it) :
create table SITE_JUNC
(primkey number RAW(16) DEFAULT SYS_GUID() PRIMARY KEY,
....)
Starting Oracle 12c, you have Identity columns.

Autoincrement in SQLite tables

I create a table, lets name it CUSTOMERS in SQLite:
CREATE TABLE "CUSTOMERS" (
"tel" INTEGER NOT NULL,
"customer" VARCHAR ,
);
When I see the table from a GUI (I use SQLite Manager from Firefox), I noticed that there is an extra column rowid which is working like auto-increment. My question is, in tables where I don't use a primary key should I specify a column like:
ROWID INTEGER PRIMARY KEY AUTOINCREMENT
If I execute this query PRAGMA table_info(CUSTOMERS); I get only the two columns tel,customer.
Sqlite usually adds a rowid automatically as #laato linked in the comments SqLite : ROWID
That can be removed, but does not need to be specified. So there is no need to add it to the Create Table.
The hidden rowid allows delete's to be targetted at a single row, bu
t if you are using the ROWID as a specific foreign key, it would be better to name a column explicitly. That will then become a synonym with the rowid.
You can see here, as it was commented in your question.
However, if you are in a dilemma what to choose between these options, SQLite recommends that you should not use AUTOINCREMENT attribute because:
The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and
disk I/O overhead and should be avoided if not strictly needed. It is
usually not needed.
More info you can read here.

Create Table with deferred foreign key referencing each other

I'm new to sqlite and sql in gerneral so I don't know if my approach is reasonable.
I want to model inventory items that can be created, lent, returned and discarded.
I want to model this using two tables, one for items, containing an id, a name and a reference to the last transaction (created, lent, returned, ...) and a table of transactions containing an id transaction type, date, and a reference to the item.
Since creating only one table leaves the database in an inconsitent state with one table referencing a non existant table I thought of using a transaction to crate both tables at once, and defining the foreign keys as deferrable. Creation of a new item would have to be done together in one transaction with creating a "created" event to leave the database in a consistent state.
The following code gives me the error Query Error: not an error Unable to execute multiple statements at a time in sqliteman on linux.
PRAGMA foreign_keys = ON;
begin transaction;
create table items (
id integer primary key,
name char(30),
foreign key (last_transaction) references transactions(transaction_id) DEFERRABLE INITIALLY DEFERRED
);
create table transactions(
transaction_id integer primary key,
text char(100)
foreign key (item) references items(id) DEFERRABLE INITIALLY DEFERRED
);
commit transaction;
Does my approach make sense at all?
If yes, why does the code not work? (Did I make a mistake somewhere, or is what I'm trying impossible in mysql?)
Note: simply creating the tables in one transaction without the foreign key constraints gives the same error. (Could this be a similar Problem to: this question)

Wrong autoincrement value in sqlite using JPA

I'm working on a simple project using sqlite, JPA and eclipseLink.
First I create my Person table in my database with this:
CREATE TABLE Person (
idPerson INTEGER PRIMARY KEY AUTOINCREMENT,
firstname TEXT DEFAULT 'NULL',
birthdate DATETIME DEFAULT 'NULL'
)
and then add a new test entry (in order to generate the sqlite_sequence table)
INSERT INTO [Person] ([firstname], [birthdate]) VALUES ('Foo', '1145-11-12 00:00:00')
All the successive insertion are done using JPA, where in the Person class I use this notation for the person id:
#GeneratedValue(generator="sqlite_person")
#TableGenerator(name="sqlite_person", table="sqlite_sequence",
pkColumnName="name", valueColumnName="seq",
pkColumnValue="Person")
#Column(name="idPerson")
private int id;
The first JPA insertion is ok (that is, new new inserted person has id = 2) but then I get an increment of 50 instead of only 1 (so the third inserted person has id = 52, the fourth 102 and so on).
I read that "making modifications to this table will likely perturb the AUTOINCREMENT key generation algorithm" [ref]
Is my problem related to this, even if in theory I'm not modifying that table?
Any kind of suggestion in order to resolve the problem?
You are using Autoincrement in the database, which means the database will assign a value to the id when it is inserted, but then you tell the JPA provider to use Table generation. Table generation requires that the JPA provider use a special table to keep track of sequence values, looking it up and assigning it before inserting the entity row in the database. This conflicts with what you set up in the database.
http://wiki.eclipse.org/EclipseLink/Examples/JPA/PrimaryKey explains sequencing fairly well. You will need to try using #GeneratedValue(strategy=GenerationType.IDENTITY) instead of table generation so that inserts by JPA use the same sequence allocation as inserts outside of JPA.
At the end, in order to solve the problem, I just added two optional elements for the TableGenerator annotation (i.e. initialValue, allocationSize).
So the new annotation for the ID is like this:
#GeneratedValue(generator="sqlite_person")
#TableGenerator(name="sqlite_person", table="sqlite_sequence",
pkColumnName="name", valueColumnName="seq",
pkColumnValue="Person",
initialValue=1, allocationSize=1)
#Column(name="idPerson")
private int id;
I think it works also without the initial value, but like this I also avoid to insert random entries (because it seems that the sqlite_sequence table is automatically generated already when I create the Person table)

Resources