How could I check - does my SQLite3 database is empty? - python

I am using Python 2.7 and SQLite3.
When I starting work with DB I want to check - does my database is empty or on not. I mean does it already have any tables or not.
My idea is to use the simple SELECT from any table. And wrap this select in try:exception block. So if exception was raised then my DB is empty.
Maybe someone know the better way for checking?

SELECT name FROM sqlite_master
while connected to your database will give you all the tables names. you can then do a fetchall and check the size, or even contents of the list. not try/catch necessary (the list will be empty if the database doesn't contain any tables)

Related

Effective insert-only permissions for peewee tables

I'm wondering what the best strategy is for using insert-only permissions to a postgres db with Peewee. I'd like this in order to be certain that a specific user can't read any data back out of the database.
I granted INSERT permissions to my table, 'test', in postgres. But I've run into the problem that when I try to save new rows with something like:
thing = Test(value=1)
thing.save()
The sql actually contains a RETURNING clause that needs more permissions (namely, SELECT) than just insert:
INSERT INTO "test" ("value") VALUES (1) RETURNING "test"."id"
Seems like the same sql is generated when I try to use query = test.insert(value=1)' query.execute() as well.
From looking around, it seems like you need either grant SELECT privileges, or use a more exotic feature like "row level security" in Postgres. Is there any way to go about this with peewee out of the box? Or another suggestion of how to add new rows with truly write-only permissions?
You can omit the returning clause by explicitly writing your INSERT query and supplying a blank RETURNING. Peewee uses RETURNING whenever possible so that the auto-generated PK can be recovered in a single operation, but it is possible to disable it:
# Empty call to returning will disable the RETURNING clause:
iq = Test.insert(value=1).returning()
iq.execute()
You can also override this for all INSERT operations by setting the returning_clause attribute on the DB to False:
db = PostgresqlDatabase(...)
db.returning_clause = False
This is not an officially supported approach, though, and may have unintended side-effects or weird behavior - caveat emptor.

Inserting into SQL with pyodbc from remote computer

Hello I am using my second computer to gather some data and insert it into the SQL database. I set up everything when it comes to reading and writing the database remotely, and I can insert new rows just by using the normal SQL.
With pyodbc I can read tables, but when I insert new data, nothing happens. No error message, but also no new rows in the table.
I wonder if anyone has faced this issue before and knows what the solution is.
The cursor.execute() method only prepares the SQL statement. Then, since this is an INSERT statement, you must use the cursor.commit() method for the records to actually populate your table. Likewise for a DELETE statement, you need to commit, as well.
Without more perspective here, I can only assume that you are not committing the insert.
Notice, similarly, that when you run cursor.execute("""select * from yourTable"""), you need to run cursor.fetchall() or another fetch statement to actually retrieve and view your query.

Did CREATE TABLE IF NOT EXISTS create the table?

import sqlite3
connection = sqlite3.connect("...")
cursor = connection.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS ...")
How can I find out, after executing the CREATE TABLE IF NOT EXISTS, whether the table was created or already in place?
The only way to check is by removing the IF NOT EXISTS part of the query and checking for a sqlite3.OperationalError with a message of the form "table $tablename already exists". I wouldn't trust the error message to be stable, but Python apparently does not supply an error code along with the exception.
The safest thing to do would be to begin a transaction and query the sqlite_master table beforehand, create the table if there were no results, then commit the transaction.
Note that none of these solutions will work correctly if the table you are attempting to create has a different schema than the one that exists in the database; database migrations are more complicated and usually require case-by-case handling.
EDIT: Updated answer
It sounds like you don't know beforehand what tables might exist, what those tables have in them (if anything), or have a way to check beforehand if tables exist.
To check if a table was created after using the IF NOT EXISTS clause on a CREATE TABLE command, you could try one of these:
Make the "new" table have at least one column name that is guaranteed to be different from the old table. After the CREATE TABLE command, you select the column guaranteed to be new.
CREATE TABLE newTable IF NOT EXISTS (column1 INTEGER, somethingUnique INTEGER)
SELECT somethingUnique FROM newTable
If you don't get back an error from selecting somethingUnique, then you know that you have created a new table, else the table already existed. If you end up creating a new table and do not want that somethingUnique column anymore, then you can just delete that column.
Even if you don't want to make a somethingUnique column, there is the possibility that if the old table existed, it would have at least one row in it already. All you have to do is select anything from the table. If nothing returned, then you may or may not be dealing with your new table (so go back to suggestion 1). If something does get returned, then you know that you are dealing with an old table.
Old answer
One way to see if the table was created (or exists) is to go into a terminal, navigate to the directory where your database is, and then use sqlite commands.
$ sqlite3
sqlite> .open yourDatabase.db
sqlite> SELECT * FROM theTableYouWantedToCreate;
If the table does not exist, you would get back the following error:
Error: no such table: theTableYouWantedToCreate
If the table did exist, obviously it would return everything that is in the table. If nothing is in the table (since you just created it), sqlite will give you back another prompt, indicating that the table does indeed exist.

Check for duplicates in sqlite3 database and return error if any

I have a sqlite3 database file with multiple tables, each one with different values, what i want to do now is to check if a value already exists in any table when inserting it to the table and if it already exists returns an error or something.
This is because I'm doing a program t help nurses have a database with their patient and check if a patient has already been inserted into the database, I dont post any code because i'm gathering all the information needed before programming anything to avoid spaghetti code
Try adding a constraint to each or just one of your columns so I doesn't allow duplicates to be added
Like this:
CONSTRAINT <Constraint Name> UNIQUE (<column1>,<column2>)
Then in your code you could catch the SQL exception and return a custom message

getting the id of a created record in SQLAlchemy

How can I get the id of the created record in SQLAlchemy?
I'm doing:
engine.execute("insert into users values (1,'john')")
When you execute a plain text statement, you're at the mercy of the DBAPI you're using as to whether or not the new PK value is available and via what means. With SQlite and MySQL DBAPIs you'll have it as result.lastrowid, which just gives you the value of .lastrowid for the cursor. With PG, Oracle, etc., there's no ".lastrowid" - as someone else said you can use "RETURNING" for those in which case results are available via result.fetchone() (although using RETURNING with oracle, again not taking advantage of SQLAlchemy expression constructs, requires several awkward steps), or if RETURNING isn't available you can use direct sequence access (NEXTVAL in pg), or a "post fetch" operation (CURRVAL in PG, ##identity or scope_identity() in MSSQL).
Sounds complicated right ? That's why you're better off using table.insert(). SQLAlchemy's primary system of providing newly generated PKs is designed to work with these constructs. One you're there, the result.last_inserted_ids() method gives you the newly generated (possibly composite) PK in all cases, regardless of backend. The above methods of .lastrowid, sequence execution, RETURNING etc. are all dealt with for you (0.6 uses RETURNING when available).
There's an extra clause you can add: RETURNING
ie
INSERT INTO users (name, address) VALUES ('richo', 'beaconsfield') RETURNING id
Then just retrieve a row like your insert was a SELECT statement.

Categories