I have a table in my PostgreSQL:
CREATE SEQUENCE dember_id_seq INCREMENT BY 1 MINVALUE 1 START 1;
CREATE TABLE dember (id INT NOT NULL, did VARCHAR(255) DEFAULT NULL, dnix VARCHAR(255) DEFAULT NULL, durl TEXT DEFAULT NULL, created TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, modified TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, status BOOLEAN NOT NULL, dnickname VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id));
When I want to insert a record, I using the following code:
import pg
db = pg.DB(....)
db.insert('dember',{'did':did,'dnix':dnix,'durl',durl,'created',now, 'modified':now, 'status':'true','dnickname':nickname'})
Then the insert code does not work, I get the following error:
pg.ProgrammingError: ERROR: null value in column "id" violates not-null constraint
It looks that I have to add {'id':number} to the value dictionary.
Any suggestions? Thanks.
You should save yourself some trouble and use serial instead of int:
The data types serial and bigserial are not true types, but merely a notational convenience for creating unique identifier columns (similar to the AUTO_INCREMENT property supported by some other databases).
So saying:
create table t (
id serial not null primary key
-- ...
)
will create id as an integer column, create a sequence for it, set the default value of id to be the next value in the sequence, and set the sequence's owner to the id column; the last bit is important, the implied
ALTER SEQUENCE t_id_seq OWNED BY t.id;
that a serial type does ensures that the sequence will be dropped when the column goes away. If you don't set the sequence's owner, you can be left with dangling unused sequences in your database.
You forgot to assign the sequence to the column.
CREATE TABLE dember (id INT NOT NULL DEFAULT nextval('dember_id_seq'), ...
Related
I am facing the following error using SQLAlchemy: Unconsumed column names: company
I want to insert data for 1 specific column, and not all columns in the table: INSERT INTO customers (company) VALUES ('sample name');
My code:
engine.execute(table('customers').insert().values({'company': 'sample name'}))
Create Table:
'CREATE TABLE `customers` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`company` varchar(255) DEFAULT NULL,
`first_name` varchar(255) DEFAULT NULL,
`last_name` varchar(255) DEFAULT NULL,
`phone` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
UNIQUE KEY `company_UNIQUE` (`company`)
) ENGINE=InnoDB AUTO_INCREMENT=63 DEFAULT CHARSET=utf8'
After hours of frustration, I was able to test a way that I think works for my use case. As we know, you can insert to specific columns, or all columns in a table. In my use case, I dynamically need to insert to the customers table, depending on what columns a user has permissions to insert to.
I found that I needed to define all columns in the table() method of sqlalchemy, but I can pass in whatever columns and values that I need dynamically to the values() method.
Final code:
engine.execute(table('customers', column('company'), column('first_name'), column('last_name'), column('email'), column('phone')).insert().values({'company': 'sample name'}))
The original solution works great, however I'd like to add another approach that will allow working with tables dynamically, without specifying all of their columns. This can be useful when working with multiple tables.
We can use the Table class from sqlalchemy.schema and provide our engine to its autoload_with parameter, which will reflect the schema and populate the columns for us.
Then, we can work just like we in the OP's answer.
from sqlalchemy.schema import Table, MetaData
my_table_name = 'customers' # Could be passed as an argument as well :)
table = Table(my_table_name, MetaData(), autoload_with=engine)
engine.execute(my_table.insert({'company': 'sample name'}))
how to block the possibility of adding the same values to the database, for example e-mail addresses in python and MySQL?
From database perspective, you would typically put a unique constraint on the corresponding table column:
create table users (
id int auto_increment primary key,
name varchar(50) not null,
email varchar(100) not null unique
);
With this set up in place, any query that would attempt generating a duplicate email (either from an INSERT or an UPDATE) would fail with a unique contraint violation error.
I am using a python code to create MySQL tables.
I am fine to create table using a specific name for my columns, but as soon as I want to change them, the tables are not created anymore.
This code bellow works without any problems
DROP TABLE IF EXISTS sector_tb;
CREATE TABLE sector_tb (
id INT NOT NULL AUTO_INCREMENT,
sector VARCHAR(255) NOT NULL DEFAULT '',
district_id INT NOT NULL,
PRIMARY KEY (id),
UNIQUE INDEX sector (sector)
)
COLLATE='latin1_swedish_ci'
;
As soon as I decide to change the name of 'sector' to 'sector1' or anything else, MySQL does not create the table anymore. The code below does not create the table anymore.
CREATE TABLE sector_tb (
id INT NOT NULL AUTO_INCREMENT,
sector1 VARCHAR(255) NOT NULL DEFAULT '',
district_id INT NOT NULL,
PRIMARY KEY (id),
UNIQUE INDEX sector (sector)
)
COLLATE='latin1_swedish_ci'
;
There are no errors shown while running the code.
There is an obvious error in second statement:
column name in the index doesn't match column name in the table.
sector1 VARCHAR(255)
UNIQUE INDEX sector (sector)
If your Python code does not report any errors, you must improve error handling.
Two options - drop the original sector_tb and run your second script or rename your column using the alter table command.
This is my code:
conn.execute("""
CREATE TABLE IF NOT EXISTS Blockchain_transactions(
hash_of_previous_block CHAR PRIMARY KEY DEFAULT NULL,
id INTEGER DEFAULT NULL,
transaction CHAR DEFAULT NULL
);""")
It generates a syntax error
sqlite3.OperationalError: near "transaction": syntax error
REMARK: This comes earlier in my code and does not generate the same error
conn.execute("""
CREATE TABLE IF NOT EXISTS Blockchain_blocks (
hash_of_previous_block CHAR PRIMARY KEY DEFAULT NULL,
proof_of_work INTEGER DEFAULT NULL,
difficulty INTEGER DEFAULT NULL
);""")
transaction is a sqlite keyword.
Change the column name to something different and it will work.
Avoid reserved keywords for column names, or escape them like this:
conn.execute("""
CREATE TABLE IF NOT EXISTS Blockchain_transactions(
hash_of_previous_block CHAR PRIMARY KEY DEFAULT NULL,
id INTEGER DEFAULT NULL,
`transaction` CHAR DEFAULT NULL
);""")
Other possibilities to escape / quote keywords can be found in the linked keywords page.
I am using sqlite with python 2.5. I get a sqlite error with the syntax below. I looked around and saw AUTOINCREMENT on this page http://www.sqlite.org/syntaxdiagrams.html#column-constraint but that did not work either. Without AUTO_INCREMENT my table can be created.
An error occurred: near "AUTO_INCREMENT": syntax error
CREATE TABLE fileInfo
(
fileId int NOT NULL AUTO_INCREMENT,
name varchar(255),
status int NOT NULL,
PRIMARY KEY (fileId)
);
This is addressed in the SQLite FAQ. Question #1.
Which states:
How do I create an AUTOINCREMENT
field?
Short answer: A column declared
INTEGER PRIMARY KEY will
autoincrement.
Here is the long answer: If you
declare a column of a table to be
INTEGER PRIMARY KEY, then whenever you
insert a NULL into that column of the
table, the NULL is automatically
converted into an integer which is one
greater than the largest value of that
column over all other rows in the
table, or 1 if the table is empty. (If
the largest possible integer key,
9223372036854775807, then an unused
key value is chosen at random.) For
example, suppose you have a table like
this:
CREATE TABLE t1( a INTEGER PRIMARY
KEY, b INTEGER ); With this table,
the statement
INSERT INTO t1 VALUES(NULL,123); is
logically equivalent to saying:
INSERT INTO t1 VALUES((SELECT max(a)
FROM t1)+1,123); There is a function
named sqlite3_last_insert_rowid()
which will return the integer key for
the most recent insert operation.
Note that the integer key is one
greater than the largest key that was
in the table just prior to the insert.
The new key will be unique over all
keys currently in the table, but it
might overlap with keys that have been
previously deleted from the table. To
create keys that are unique over the
lifetime of the table, add the
AUTOINCREMENT keyword to the INTEGER
PRIMARY KEY declaration. Then the key
chosen will be one more than than the
largest key that has ever existed in
that table. If the largest possible
key has previously existed in that
table, then the INSERT will fail with
an SQLITE_FULL error code.
It looks like AUTO_INCREMENT should be AUTOINCREMENT see http://www.sqlite.org/syntaxdiagrams.html#column-constraint
You could try
CREATE TABLE fileInfo
(
fileid INTEGER PRIMARY KEY AUTOINCREMENT,
name STRING,
status INTEGER NOT NULL
);
We just changed the order from
NOT NULL, AUTO_INCREMENT
to
AUTO_INCREMENT NOT NULL,
an example :
cursor.execute("CREATE TABLE users(\
user_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\
user_name VARCHAR(100) NOT NULL)")