Populate complex SQL Database with python via reflection? - python

I have a relatively complex MySQL Database (60+ Tables) that I need to populate regularly. There are a lot of foreign key constraints on most of the tables. I started writing my import engine using SQL Alchemy.
Do I need to reconstruct my entire Database with SQL Alchemy classes in order to do this? Does anyone have any better suggestions? Only 8 of the tables actually accept new raw data, the rest are populated from these tables.

You can use SQLAlchemy reflection to create the classes mapped to MySQL table structure. See Reflecting Database Objects. There is a subchapter there showing how to reflect all tables (Reflecting Database Objects).
Code copied from the above link to reflect one table:
messages = Table('messages', meta, autoload=True, autoload_with=engine)
All tables:
meta = MetaData()
meta.reflect(bind=someengine)
users_table = meta.tables['users']
addresses_table = meta.tables['addresses']

Related

Creating Hypertables through SQL Alchemy

Our current project relies heavily on SQL Alchemy for table creation/data insertion. We would like to switch to timescaledb's hypertables, but it seems the recommended way to create hypertables is by executing a
create_hypertable
command. I need to be able to dynamically create tables, and so manually doing this for every table created is not really an option. One way of handling the conversion is to run a python script sending psycopg2 commands to convert all newly-created tables into hypertables, but this seems a little clumsy. Does timescaledb offer any integration with SQL Alchemy with regards to creating hypertables?
We currently do not offer any specific integrations with SQL Alchemy (broadly or specifically for creating hypertables). We are always interested in hearing new feature requests, so if you wanted to post your issue/use case on our Github it would help us keep better track of it for future work.
One thing that might work for your use case is to create an event trigger that executes on table creation. You'd have to check that it's in the correct schema since TimescaleDB creates its own chunk tables dynamically and you don't want to have them converted to hypertables.
See this answer for more info on event triggers:
execute a trigger when I create a table
Here is a practical example of using event trigger to create a hyper table:
from sqlalchemy import Column, Integer, DateTime, event, DDL, orm
Base = orm.declarative_base()
class ExampleModel(Base):
__tablename__ = 'example_model'
id = Column(Integer, primary_key=True)
time = Column(DateTime)
event.listen(
ExampleModel.__table__,
'after_create',
DDL(f"SELECT create_hypertable('{ExampleModel.__tablename__}', 'time');")
)

Execute stored procedure with table param sqlalchemy

I've been trying to write a bulk insert to a table.
I've already connected and tried to use SQLAlchemy bulk insert functions, but it's not really bulk inserting, it inserts the rows one by one (the dba tracked the db and showed me).
I wrote a class for the table:
Class SystemLog(Base):
__tablename__ = 'systemlogs'
# fields goes here...
Because of the fact that the bulk insert functions doesn't work I want to try to use a stored procedure.
I have a stored procedure named 'insert_new_system_logs' that receives a tablevar as a parameter.
How can I call it with a table from python SQLAlchemy?
My SQLAlchemy version is 1.0.6
I can't paste my code because it's in a closed network.
I don't have to use SQLAlchemy, I just want to bulk insert my logs.

SqlAlchemy Reflection of Oracle Table Not Owned

I'm working with SQLAlchemy to run SQL queries against an Oracle database. I have read access to the database, but the user I have does not own any of the tables I'm working with.
The database updates on a regular basis, so rather than explicitly listing the MetaData, I was hoping to use reflection. I found this question, that describes an issue similar to what I'm having. However, I don't have a way to change ownership of the tables, nor modify the database in any way. I just have read access.
Is there a way to reflect Oracle tables in SQLAlchemy if I don't have ownership of those tables?
(Edit)
Example Code:
engine = create_engine('ORACLE CONNECTION STRING')
metadata = MetaData()
students = Table('students', metadata, autoload=True, autoload_with=engine)
I receive an exception of sqlalchemy.exc.NoSuchTableError: students
However, when I run the following:
results = engine.execute('SELECT * FROM students')
for r in results:
print(r)
I receive the output that I expected from the table, which is a tuple of all the fields for each row.
So instead of trying to reflect a single table, I try to reflect all of them:
metadata.reflect(bind=engine)
print(metadata.tables)
The output is immutabledict({}).
So essentially it's nothing. All of these tables are owned by user A where as I'm logging in with a read-only of user B.
You might have better luck reflecting someone else's tables if you specify the schema (account) you're targeting:
metadata.reflect(bind=engine, schema='userA')
This way, you'll reflect all readable tables belonging to 'userA'. I'm not sure why you're able to query students using engine.execute, though.

Use raw SQL to create tables in SQLAlchemy, after which use ORM

Is it possible to use raw SQL rather than the TABLE construct for creating tables in SQL Alchemy? I would still like to use the rest of SQLAlchemy though, such as the object mapper and session module. I'm just not fond of the SQLAlchemy syntax used to create tables (I've spent too long mired in SAS and SQL to learn another!).
Many thanks, Rich
Yes.
connection.execute("""
CREATE TABLE ...
""")
You can then reflect all tables: MetaData(dsn, reflect=True) or metadata_instance.reflect().
You can use the autoload paramater to the Table constructor to have it automatically load up the table definitions. There are some examples here.

Load an existing many-to-many table relation with sqlalchemy

I'm using SqlAlchemy to interact with an existing PostgreSQL database.
I need to access data organized in a many-to-many relationship. The documentation describes how to create relationships, but I cannot find an example for neatly loading and query an existing one.
Querying an existing relation is not really different than creating a new one. You pretty much write the same code but specify the table and column names that are already there, and of course you won't need SQLAlchemy to issue the CREATE TABLE statements.
See http://www.sqlalchemy.org/docs/05/mappers.html#many-to-many . All you need to do is specify the foreign key columns for your existing parent, child, and association tables as in the example, and specify autoload=True to fill out the other fields on your Tables. If your association table stores additional information, as they almost always do, you should just break your many-to-many relation into two many-to-one relations.
I learned SQLAlchemy while working with MySQL. With that database I always had to specify the foreign key relationships because they weren't explicit database constraints. You might get lucky and be able to reflect even more from your database, but you might prefer to use something like http://pypi.python.org/pypi/sqlautocode to just code the entire database schema and avoid the reflection delay.

Categories