|
| 1 | +# Introdaction to SQLAlchemy |
| 2 | + |
| 3 | +The purpose of these laboratory classes is to familiarize participants with the basic techniques of working with [SQLAlchemy](https://www.sqlalchemy.org/). |
| 4 | + |
| 5 | +The scope of this classes: |
| 6 | +- connection to a database (especially remote database), |
| 7 | +- explore of database structure using ORM, |
| 8 | +- creating simple select in ORM, |
| 9 | +- using query results in a program, |
| 10 | +- adding where clause to query. |
| 11 | + |
| 12 | + |
| 13 | +SQLAlchemy is the Python SQL toolkit and Object Relational Mapper that gives application developers the full power and flexibility of SQL. |
| 14 | + |
| 15 | +It provides a full suite of well known enterprise-level persistence patterns, designed for efficient and high-performing database access, adapted into a simple and Pythonic domain language. |
| 16 | + |
| 17 | +Object Relational Mapper (ORM) is a programming technique for converting data between incompatible type systems using object-oriented programming languages. This creates, in effect, a "virtual object database" that can be used from within the programming language. |
| 18 | + |
| 19 | + |
| 20 | +## Connection SQLAlchemy with database |
| 21 | + |
| 22 | +To connection a database with a program with the basic version we need to use the following script: |
| 23 | + |
| 24 | +```python |
| 25 | +from sqlalchemy import create_engine |
| 26 | + |
| 27 | +db_string = "database_type://user:password@database_url:port/database_name" |
| 28 | + |
| 29 | +db = create_engine(db_string) |
| 30 | +``` |
| 31 | +where: |
| 32 | +- *databae_type* is the name of database driver, more details you can read [here](https://docs.sqlalchemy.org/en/13/core/engines.html#database-urls), |
| 33 | +- *user* - name of user in database, |
| 34 | +- *password* - password to database, |
| 35 | +- *database_url* - url address to database, |
| 36 | +- *port* - port to database connection, |
| 37 | +- *database_name* - name of database. |
| 38 | + |
| 39 | +*[create_engine](https://docs.sqlalchemy.org/en/13/core/connections.html)* is just interface to connection database with program. |
| 40 | + |
| 41 | + |
| 42 | +## Explore database structure |
| 43 | +Because the database structure is not always known to the programmer for various reasons, most often due to lack of documentation. In this case, it's worth knowing that we can use SQL query to explore database structure. |
| 44 | + |
| 45 | +In all database exist metadata to describe structure of data. This data are write in *information_schema*, for PostgreSql [see](https://www.postgresql.org/docs/12/information-schema.html): |
| 46 | + |
| 47 | +```sql |
| 48 | +SELECT column_name, data_type |
| 49 | +FROM information_schema.columns |
| 50 | +WHERE table_name = 'name' AND table_schema = 'public'; |
| 51 | +``` |
| 52 | + |
| 53 | +and for MySQL [see](https://dev.mysql.com/doc/refman/8.0/en/getting-information.html): |
| 54 | + |
| 55 | +```sql |
| 56 | +SELECT table_name |
| 57 | +FROM information_schema.tables |
| 58 | +WHERE table_schema = 'bauer1' |
| 59 | +``` |
| 60 | + |
| 61 | +Of course, SQLAlchemy has the function to read this data: |
| 62 | + |
| 63 | +```python |
| 64 | +from sqlalchemy import create_engine, MetaData, Table |
| 65 | + |
| 66 | +print(db.table_names()) |
| 67 | + |
| 68 | +metadata = MetaData() |
| 69 | + |
| 70 | +table = Table(table_name, metadata , autoload=True, autoload_with=db) |
| 71 | + |
| 72 | +print(repr(table)) |
| 73 | + |
| 74 | +print(table.columns.keys()) |
| 75 | +``` |
| 76 | +In this sript *table_name* is the string with table name in database. |
| 77 | + |
| 78 | +## SQLAlchemy query |
| 79 | + |
| 80 | +The basic select in SQLAlchemy has form: |
| 81 | + |
| 82 | +```python |
| 83 | +stmt = 'select * from table' |
| 84 | + |
| 85 | +# Execute the statement and fetch the results |
| 86 | +results = db.execute(stmt).fetchall() |
| 87 | + |
| 88 | +# Print results |
| 89 | +print(results) |
| 90 | +``` |
| 91 | +Function *execute* make a request to a database and *fetchall* method get our results from an executed query. But in this case we don't use ORM propertis. More correctly is use structur: |
| 92 | + |
| 93 | +```python |
| 94 | +from sqlalchemy import select |
| 95 | + |
| 96 | +stmt = select([table]) |
| 97 | + |
| 98 | +# Print the SQL query string |
| 99 | +print(stmt) |
| 100 | + |
| 101 | +# Execute the statement and fetch with limit the results |
| 102 | +results = db.execute(stmt).fetchmany(size=10) |
| 103 | +print(results) |
| 104 | +``` |
| 105 | +In this case, the ORM system creates a query based on information in object *table*. |
| 106 | + |
| 107 | +### Read result from query |
| 108 | +The variable *results* can be read as follows: |
| 109 | + |
| 110 | +1. Print n row of the results: |
| 111 | + |
| 112 | +```python |
| 113 | +print(results[n]) |
| 114 | +``` |
| 115 | +2. Print the first column of a n row by accessing it by its index: |
| 116 | + |
| 117 | +```python |
| 118 | +print(first_row[:][n]) |
| 119 | +``` |
| 120 | +3. Print the column by name of the a n row by using its name |
| 121 | + |
| 122 | +```python |
| 123 | +print(results[n][name]) |
| 124 | +``` |
| 125 | + |
| 126 | +### Adding constraint to query |
| 127 | + Adding a restriction to a query involves entering the *where* function as follows: |
| 128 | + ```python |
| 129 | +stmt = select([table]) |
| 130 | + |
| 131 | +# Add a where clause to filter the results |
| 132 | +stmt = stmt.where(table.columns.column_name == 10) |
| 133 | + |
| 134 | +# Execute the query to retrieve all the data returned: results |
| 135 | +results = db.execute(stmt).fetchall() |
| 136 | + |
| 137 | +# Loop over the results and print the column_name_1 and column_name_2 |
| 138 | +for result in results: |
| 139 | + print(result.column_name_1, result.column_name_2) |
| 140 | + ``` |
| 141 | + |
| 142 | + |
| 143 | +## Exercises: |
| 144 | +Write script to conection to databases and perform the following tasks: |
| 145 | + |
| 146 | +For PostgreSql database structure are describe [here](https://www.postgresqltutorial.com/postgresql-sample-database/): |
| 147 | +1. Create a script to connection with database. |
| 148 | +1. Based on *information_schema*, present how to explore the relationships between the tables: |
| 149 | + 1. staff and country |
| 150 | + 2. actor, language and film |
| 151 | +1. How many categories of films are in the rental? |
| 152 | +1. Display list of categories with limit 2. |
| 153 | +1. Find the oldest and youngest film in rental. |
| 154 | +1. Find all actor with a name: Olympia, Julia, Ellen. How can you check correction of your query? |
| 155 | + |
| 156 | +For MySQL database structure are describe [here](https://www.mysqltutorial.org/mysql-sample-database.aspx): |
| 157 | +1. Create a script to connection with database. |
| 158 | +1. Based on *information_schema*, present how to explore the relationships between the tables: |
| 159 | + 1. customers and employees |
| 160 | + 2. customers, payments and orders |
| 161 | +1. How many products are in the store? |
| 162 | +1. Display list of offices with limit 5. |
| 163 | +1. Find the oldest and youngest payments in rental. |
| 164 | + |
| 165 | + |
| 166 | + |
| 167 | + |
0 commit comments