Author: alien

  • Khóa học miễn phí SQL – Subqueries to Solve Queries nhận dự án làm có lương

    SQL – Subqueries to Solve Queries



    A subquery is best defined as a query within a query. Subqueries enable you to write queries that select data rows for criteria that are actually developed while the query is executing at run time. More formally, it is the use of a SELECT statement inside one of the clauses of another SELECT statement. In fact, a subquery can be contained inside another subquery, which is inside another subquery, and so forth. A subquery can also be nested inside INSERT, UPDATE, and DELETE statements. Subqueries must be enclosed within parentheses.

    A subquery can be used any place where an expression is allowed providing it returns a single value. This means that a subquery that returns a single value can also be listed as an object in a FROM clause listing. This is termed an inline view because when a subquery is used as part of a FROM clause, it is treated like a virtual table or view. Subquery can be placed either in FROM clause, WHERE clause or HAVING clause of the main query.

    Oracle allows a maximum nesting of 255 subquery levels in a WHERE clause. There is no limit for nesting subqueries expressed in a FROM clause.In practice, the limit of 255 levels is not really a limit at all because it is rare to encounter subqueries nested beyond three or four levels.

    A subquery SELECT statement is very similar to the SELECT statement used to begin a regular or outer query.The complete syntax of a subquery is:

    ( SELECT [DISTINCT] subquery_select_parameter
      FROM {table_name | view_name}
                   {table_name | view_name} ...
      [WHERE search_conditions]
      [GROUP BY column_name [,column_name ] ...]
      [HAVING search_conditions] )
    

    Types of Subqueries

    Single Row Sub Query: Sub query which returns single row output. They mark the usage of single row comparison operators, when used in WHERE conditions.

    Multiple row sub query: Sub query returning multiple row output. They make use of multiple row comparison operators like IN, ANY, ALL. There can be sub queries returning multiple columns also.

    Correlated Sub Query: Correlated subqueries depend on data provided by the outer query.This type of subquery also includes subqueries that use the EXISTS operator to test the existence of data rows satisfying specified criteria.

    Single Row Sub Query

    A single-row subquery is used when the outer query”s results are based on a single, unknown value. Although this query type is formally called “single-row,” the name implies that the query returns multiple columns-but only one row of results. However, a single-row subquery can return only one row of results consisting of only one column to the outer query.

    In the below SELECT query, inner SQL returns only one row i.e. the minimum salary for the company. It in turn uses this value to compare salary of all the employees and displays only those, whose salary is equal to minimum salary.

    SELECT first_name, salary, department_id
    FROM employees
    WHERE salary = (SELECT MIN (salary)
    		FROM employees); 

    A HAVING clause is used when the group results of a query need to be restricted based on some condition. If a subquery”s result must be compared with a group function, you must nest the inner query in the outer query”s HAVING clause.

    SELECT department_id, MIN (salary)
    FROM employees
    GROUP BY department_id
    HAVING MIN (salary)  < (SELECT AVG (salary)
    			FROM employees)

    Multiple Row Sub Query

    Multiple-row subqueries are nested queries that can return more than one row of results to the parent query. Multiple-row subqueries are used most commonly in WHERE and HAVING clauses. Since it returns multiple rows,it must be handled by set comparison operators (IN, ALL, ANY).While IN operator holds the same meaning as discussed in earlier chapter, ANY operator compares a specified value to each value returned by the sub query while ALL compares a value to every value returned by a sub query.

    Below query shows the error when single row sub query returns multiple rows.

    SELECT	first_name, department_id
    FROM employees
    WHERE department_id = (SELECT department_id
    			FROM employees
    			WHERE LOCATION_ID = 100)
    department_id = (select
                   *
    ERROR at line 4:
    ORA-01427: single-row subquery returns more than one row 

    Usage of Multiple Row operators

    • [> ALL] More than the highest value returned by the subquery

    • [< ALL] Less than the lowest value returned by the subquery

    • [< ANY] Less than the highest value returned by the subquery

    • [> ANY] More than the lowest value returned by the subquery

    • [= ANY] Equal to any value returned by the subquery (same as IN)

    Above SQL can be rewritten using IN operator like below.

    SELECT	first_name, department_id
    FROM employees
    WHERE department_id IN (SELECT department_id
                       	    FROM departments
                       	    WHERE LOCATION_ID = 100)

    Note in the above query, IN matches department ids returned from the sub query,compares it with that in the main query and returns employee”s name who satisfy the condition.

    A join would be better solution for above query, but for purpose of illustration, sub query has been used in it.

    Correlated Sub Query

    As opposed to a regular subquery, where the outer query depends on values provided by the inner query,a correlated subquery is one where the inner query depends on values provided by the outer query. This means that in a correlated subquery,the inner query is executed repeatedly, once for each row that might be selected by the outer query.

    Correlated subqueries can produce result tables that answer complex management questions.

    Consider the below SELECT query. Unlike the subqueries previously considered, the subquery in this SELECT statement cannot be resolved independently of the main query. Notice that the outer query specifies that rows are selected from the employee table with an alias name of e1. The inner query compares the employee department number column (DepartmentNumber) of the employee table with alias e2 to the same column for the alias table name e1.

    SELECT EMPLOYEE_ID, salary, department_id
    FROM   employees E
    WHERE salary > (SELECT AVG(salary)
                    FROM   EMP T
                    WHERE E.department_id = T.department_id)

    Multiple Column Sub Query

    A multiple-column subquery returns more than one column to the outer query and can be listed in the outer query”s FROM, WHERE, or HAVING clause. For example, the below query shows the employee”s historical details for the ones whose current salary is in range of 1000 and 2000 and working in department 10 or 20.

    SELECT first_name, job_id, salary
    FROM emp_history
    WHERE (salary, department_id) in (SELECT salary, department_id
    				  FROM employees
     				  WHERE salary BETWEEN 1000 and 2000
    				  AND department_id BETWEEN 10 and 20)
    ORDER BY first_name;

    When a multiple-column subquery is used in the outer query”s FROM clause, it creates a temporary table that can be referenced by other clauses of the outer query. This temporary table is more formally called an inline view. The subquery”s results are treated like any other table in the FROM clause. If the temporary table contains grouped data, the grouped subsets are treated as separate rows of data in a table. Consider the FROM clause in the below query. The inline view formed by the subquery is the data source for the main query.

    SELECT *
    FROM (SELECT salary, department_id
    	FROM employees
     	WHERE salary BETWEEN 1000 and 2000);

    Khóa học lập trình tại Toidayhoc vừa học vừa làm dự án vừa nhận lương: Khóa học lập trình nhận lương tại trung tâm Toidayhoc

  • Khóa học miễn phí SQL – The SQL SELECT Statement nhận dự án làm có lương

    SQL – The SQL SELECT Statement



    Retrieving data using the SQL Select Statement

    SQL is a comprehensive database language. SQL, pronounced Sequel or simply S-Q-L, is a computer programming language used for querying relational databases following a nonprocedural approach. When you extract information from a database using SQL, this is termed querying the database.

    A relational database is implemented through the use of a Relational Database Management System (RDBMS). An RDBMS performs all the basic functions of the DBMS software mentioned above along with a multitude of other functions that make the relational model easier to understand and to implement. RDBMS users manipulate data through the use of a special data manipulation language. Database structures are defined through the use of a data definition language. The commands that system users execute in order to store and retrieve data can be entered at a terminal with an RDBMS interface by typing the commands, or entered through use of some type of graphical interface. The DBMS then processes the commands.

    Capabilities of the SELECT Statement

    Data retrieval from data base is done through appropriate and efficient use of SQL. Three concepts from relational theory encompass the capability of the SELECT statement: projection, selection, and joining.

    • Projection: A project operation selects only certain columns (fields) from a table. The result table has a subset of the available columns and can include anything from a single column to all available columns.

    • Selection: A select operation selects a subset of rows (records) in a table (relation) that satisfy a selection condition. The ability to select rows from out of complete result set is called Selection. It involves conditional filtering and data staging. The subset can range from no rows, if none of the rows satisfy the selection condition, to all rows in a table.

    • Joining: A join operation combines data from two or more tables based on one or more common column values. A join operation enables an information system user to process the relationships that exist between tables. The join operation is very powerful because it allows system users to investigate relationships among data elements that might not be anticipated at the time that a database is designed.

    Joining scenario of EMPLOYEES and DEPARTMENTS table

    Consider the above table structures. Fetching first_name name, department_id and salary for a single employee from EMPLOYEES table is Projection. Fetching employee details whose salary is less than 5000, from EMPLOYEES table is Selection. Fetching employee”s first name, department name by joining EMPLOYEES and DEPARTMENTS is Joining.

    Basic SELECT statement

    The basic syntax for a SELECT statement is presented below.

    SELECT  [DISTINCT | ALL] {* | select_list}
    FROM {table_name [alias] | view_name}
        [{table_name [alias]  | view_name}]...
    [WHERE  condition]
    [GROUP BY  condition_list]
    [HAVING  condition]
    [ORDER BY  {column_name | column_#  [ ASC | DESC ] } ...
    

    The SELECT clause is mandatory and carries out the relational project operation.

    The FROM clause is also mandatory. It identifies one or more tables and/or views from which to retrieve the column data displayed in a result table.

    The WHERE clause is optional and carries out the relational select operation. It specifies which rows are to be selected.

    The GROUP BY clause is optional. It organizes data into groups by one or more column names listed in the SELECT clause.

    The optional HAVING clause sets conditions regarding which groups to include in a result table. The groups are specified by the GROUP BY clause.

    The ORDER BY clause is optional. It sorts query results by one or more columns in ascending or descending order.

    Arithmetic expressions and NULL values in the SELECT statement

    An arithmetic expression can be created using the column names, operators and constant values to embed an expression in a SELECT statement. The operator applicable to a column depends on column”s data type. For example, arithmetic operators will not fit for character literal values. For example,

    SELECT employee_id, sal * 12 ANNUAL_SAL
    FROM employees;
    

    The above query contains the arithmetic expression (sal * 12) to calculate annual salary of each employee.

    Arithmetic operators

    Operators act upon the columns (known as operands) to result into a different result. In case of multiple operators in an expression, the order of evaulation is decided by the operator precedence. Here are the elementary rules of precedence –

    • Multiplication and division occur before Addition and Subtraction.

    • Operators on the same priority are evaluated from left to right.

    • Use paretheses to override the default behavior of the operators.

    Below table shows the precedence of the operators, in such cases. Precedence Level Operator Symbol Operation

    Description   Operator	Precedence
    Addition	+	Lowest
    Subtraction	-	Lowest
    Multiplication	*	Medium
    Division	/	Medium
    Brackets	( )	Highest
    

    Examine the below queries (a), (b), and (c)

    • SQL> SELECT 2*35 FROM DUAL;
    • SQL> SELECT salary + 1500 FROM employees;
    • SQL> SELECT first_name, salary, salary + (commission_pct* salary) FROM employees;

    Query (a) multiplies two numbers, while (b) shows addition of $1500 to salaries of all employees. Query (c) shows the addition of commission component to employee”s salary. As per the precedence, first commission would be calculated on the salary, and then added to the salary.

    Column Alias

    An alias is used to rename a column or an expression during display. The alias to a column or an expression appears as the heading in the output of a query. It is useful in providing a meaningful heading to long expressions in the SELECT query. By default, the alias appears in uppercase in the query output without spaces. To override this behavior, alias must be enclosed within double quotes to preserve the case and spaces in the alias name.

    SELECT price * 2 as DOUBLE_PRICE, price * 10 "Double Price"
    FROM products;
    
    DOUBLE_PRICE	Double Price
    ------------	------------
    39.9			39.9
    60			60
    51.98			51.98
    

    Concatenation operators

    Concatenation operator can be used to join two string values or expressions in a SELECT query. The double vertical bar symbol is used as string concatenation operator. It is applicable only for character and string column values resulting into a new character expression. Example

    SQL> SELECT ''ORACLE''||'' CERTIFICATION'' FROM dual;
    

    The above query shows concatenation of two character literals values.

    Literals

    Any hard coded value, which is not stored in database, in the SELECT clause, is known s Literal. It can be number, character, or date value. Character and date values must be enclosed within quotes. Consider the below SQL queries.examples of using literals of different data types in SQL queries.

    The query below uses two character literals to join them together.

    SQL> SELECT ''ORACLE''||'' CERTIFICATION'' FROM DUAL
    

    The query below uses character literals to pretty print the employee”s salary.

    SQL> SELECT first_name ||''earns''|| salary||'' as of ''|||sysdate
    FROM employees
    

    Quote Operator

    The quote operator is used to specify the quotation mark delimiter of your own. You can chose a convenient delimiter, depedning on the data.

    SELECT 	department_name|| '' Department'' ||q''[''s Manager Id: ]''|| manager_id
    FROM departments;
    

    NULL

    If a column doesn”t has a definite value, it is considered as NULL. NULL value denotes unknown or unavailable. It is not zero for numeric values, not blank space for character values.

    Columns with NULL value can be selected in a SELECT query and can be the part of an arithmetic expression. Any arithmetic expression using NULL values results into NULL. For this reason, columns with NULL value must be handled differently by specifying their alternate values using Oracle supplied functions like NVL or NULLIF.

    SQL> SELECT NULL + 1000 NUM
    FROM DUAL;
    
    NUM
    --------
    

    DISTINCT Keyword

    If the data is expected to have duplicate results, use DISTINCT keyword to eliminate duplicates and diplay only the unique results in the query output. Only the selected columns are validated for duplication and the rows will be logically eliminated from the query output. To be noted, the DISTINCT keyword must appear just after the SELECT clause.

    The simple query below demonstrates the use of DISTINCT to display unique department ids from EMPLOYEES table.

    SQL> SELECT DISTINCT DEPARTMENT_ID
    FROM employees;
    
    DEPARTMENT_ID
    ---------------
    10
    20
    30
    40
    

    DESCRIBE command

    The structural metadata of a table may be obtained by querying the database for the list of columns that comprise it using the DESCRIBE command. It will list the used column names, their null property and data type.

    Syntax:

    DESC[RIBE] [SCHEMA].object name

    For example,

    DESC EMPLOYEE

    will display the EMPLOYEE table structure i.e. columns, their data types, precision and nullable property.


    Khóa học lập trình tại Toidayhoc vừa học vừa làm dự án vừa nhận lương: Khóa học lập trình nhận lương tại trung tâm Toidayhoc

  • Khóa học miễn phí SQL – Using the Set Operators nhận dự án làm có lương

    SQL – Using the Set Operators



    Set operators are used to join the results of two (or more) SELECT statements.The SET operators available in Oracle 11g are UNION,UNION ALL,INTERSECT,and MINUS.

    The UNION set operator returns the combined results of the two SELECT statements.Essentially,it removes duplicates from the results i.e. only one row will be listed for each duplicated result.To counter this behavior,use the UNION ALL set operator which retains the duplicates in the final result.INTERSECT lists only records that are common to both the SELECT queries; the MINUS set operator removes the second query”s results from the output if they are also found in the first query”s results. INTERSECT and MINUS set operations produce unduplicated results.

    All the SET operators share the same degree of precedence among them.Instead,during query execution, Oracle starts evaluation from left to right or from top to bottom.If explicitly parentheses are used, then the order may differ as parentheses would be given priority over dangling operators.

    Points to remember –

    • Same number of columns must be selected by all participating SELECT statements.Column names used in the display are taken from the first query.

    • Data types of the column list must be compatible/implicitly convertible by oracle. Oracle will not perform implicit type conversion if corresponding columns in the component queries belong to different data type groups.For example, if a column in the first component query is of data type DATE, and the corresponding column in the second component query is of data type CHAR,Oracle will not perform implicit conversion, but raise ORA-01790 error.

    • Positional ordering must be used to sort the result set. Individual result set ordering is not allowed with Set operators. ORDER BY can appear once at the end of the query. For example,

    • UNION and INTERSECT operators are commutative, i.e. the order of queries is not important; it doesn”t change the final result.

    • Performance wise, UNION ALL shows better performance as compared to UNION because resources are not wasted in filtering duplicates and sorting the result set.

    • Set operators can be the part of sub queries.

    • Set operators can”t be used in SELECT statements containing TABLE collection expressions.

    • The LONG, BLOB, CLOB, BFILE, VARRAY,or nested table are not permitted for use in Set operators.For update clause is not allowed with the set operators.

    UNION

    When multiple SELECT queries are joined using UNION operator, Oracle displays the combined result from all the compounded SELECT queries,after removing all duplicates and in sorted order (ascending by default), without ignoring the NULL values.

    Consider the below five queries joined using UNION operator.The final combined result set contains value from all the SQLs. Note the duplication removal and sorting of data.

    SELECT 1 NUM FROM DUAL
    UNION
    SELECT 5 FROM DUAL
    UNION
    SELECT 3 FROM DUAL
    UNION
    SELECT 6 FROM DUAL
    UNION
    SELECT 3 FROM DUAL;
    
    NUM
    -------
    1
    3
    5
    6

    To be noted, the columns selected in the SELECT queries must be of compatible data type. Oracle throws an error message when the rule is violated.

    SELECT TO_DATE(''12-OCT-03'') FROM DUAL
    UNION
    SELECT ''13-OCT-03'' FROM DUAL;
    
    SELECT TO_DATE(''12-OCT-03'') FROM DUAL
           *
    ERROR at line 1:
    ORA-01790: expression must have same datatype as corresponding expression

    UNION ALL

    UNION and UNION ALL are similar in their functioning with a slight difference. But UNION ALL gives the result set without removing duplication and sorting the data. For example,in above query UNION is replaced by UNION ALL to see the effect.

    Consider the query demonstrated in UNION section. Note the difference in the output which is generated without sorting and deduplication.

    SELECT 1 NUM FROM DUAL
    UNION ALL
    SELECT 5 FROM DUAL
    UNION ALL
    SELECT 3 FROM DUAL
    UNION ALL
    SELECT 6 FROM DUAL
    UNION ALL
    SELECT 3 FROM DUAL;
    
    NUM
    -------
    1
    5
    3
    6
    3

    INTERSECT

    Using INTERSECT operator, Oracle displays the common rows from both the SELECT statements, with no duplicates and data arranged in sorted order (ascending by default).

    For example,the below SELECT query retrieves the salary which are common in department 10 and 20.As per ISO SQL Standards, INTERSECT is above others in precedence of evaluation of set operators but this is not still incorporated by Oracle.

    SELECT SALARY
    FROM employees
    WHERE DEPARTMENT_ID = 10
    INTRESECT
    SELECT SALARY
    FROM employees
    WHERE DEPARTMENT_ID = 20
    
    SALARY
    ---------
    1500
    1200
    2000

    MINUS

    Minus operator displays the rows which are present in the first query but absent in the second query, with no duplicates and data arranged in ascending order by default.

    SELECT JOB_ID
    FROM employees
    WHERE DEPARTMENT_ID = 10
    MINUS
    SELECT JOB_ID
    FROM employees
    WHERE DEPARTMENT_ID = 20;
    
    JOB_ID
    -------------
    HR
    FIN
    ADMIN

    Matching the SELECT statement

    There may be the scenarios where the compound SELECT statements may have different count and data type of selected columns. Therefore, to match the column list explicitly, NULL columns are inserted at the missing positions so as match the count and data type of selected columns in each SELECT statement. For number columns, zero can also be substituted to match the type of the columns selected in the query.

    In the below query, the data type of employee name (varchar2) and location id (number) do not match. Therefore, execution of the below query would raise error due to compatibility issue.

    SELECT DEPARTMENT_ID "Dept", first_name "Employee"
    FROM employees
    UNION
    SELECT DEPARTMENT_ID, LOCATION_ID
    FROM departments;
    
    ERROR at line 1:
    ORA-01790: expression must have same datatype as corresponding expression

    Explicitly, columns can be matched by substituting NULL for location id and Employee name.

    SELECT DEPARTMENT_ID "Dept", first_name "Employee", NULL "Location"
    FROM employees
    UNION
    SELECT DEPARTMENT_ID, NULL "Employee", LOCATION_ID
    FROM departments;

    Using ORDER BY clause in SET operations

    The ORDER BY clause can appear only once at the end of the query containing compound SELECT statements.It implies that individual SELECT statements cannot have ORDER BY clause. Additionally, the sorting can be based on the columns which appear in the first SELECT query only. For this reason, it is recommended to sort the compound query using column positions.

    The compund query below unifies the results from two departments and sorts by the SALARY column.

    SELECT employee_id, first_name, salary
    FROM employees
    WHERE department_id=10
    UNION
    SELECT employee_id, first_name, salary
    FROM employees
    WHERE department_id=20
    ORDER BY 3;

    Khóa học lập trình tại Toidayhoc vừa học vừa làm dự án vừa nhận lương: Khóa học lập trình nhận lương tại trung tâm Toidayhoc

  • Khóa học miễn phí SQL – Using Single-Row Functions nhận dự án làm có lương

    SQL – Using Single-Row Functions



    Using Single row functions to customize output

    Oracle SQL supplies a rich library of in-built functions which can be employed for various tasks. The essential capabilities of a functions can be the case conversion of strings, in-string or substring operations, mathematical computations on numeric data, and date operations on date type values. SQL Functions optionally take arguments from the user and mandatorily return a value.

    On a broader category, there are two types of functions :-

    Single Row functions – Single row functions are the one who work on single row and return one output per row. For example, length and case conversion functions are single row functions.

    Multiple Row functions – Multiple row functions work upon group of rows and return one result for the complete set of rows. They are also known as Group Functions.

    Single row functions

    Single row functions can be character functions, numeric functions, date functions, and conversion functions. Note that these functions are used to manipulate data items. These functions require one or more input arguments and operate on each row, thereby returning one output value for each row. Argument can be a column, literal or an expression. Single row functions can be used in SELECT statement, WHERE and ORDER BY clause. Single row functions can be –

    • General functions – Usually contains NULL handling functions. The functions under the category are NVL, NVL2, NULLIF, COALESCE, CASE, DECODE.

    • Case Conversion functions – Accepts character input and returns a character value. Functions under the category are UPPER, LOWER and INITCAP.

      • UPPER function converts a string to upper case.

      • LOWER function converts a string to lower case.

      • INITCAP function converts only the initial alphabets of a string to upper case.

    • Character functions – Accepts character input and returns number or character value. Functions under the category are CONCAT, LENGTH, SUBSTR, INSTR, LPAD, RPAD, TRIM and REPLACE.

      • CONCAT function concatenates two string values.

      • LENGTH function returns the length of the input string.

      • SUBSTR function returns a portion of a string from a given start point to an end point.

      • INSTR function returns numeric position of a character or a string in a given string.

      • LPAD and RPAD functions pad the given string upto a specific length with a given character.

      • TRIM function trims the string input from the start or end.

      • REPLACE function replaces characters from the input string with a given character.

    • Date functions – Date arithmetic operations return date or numeric values. Functions under the category are MONTHS_BETWEEN, ADD_MONTHS, NEXT_DAY, LAST_DAY, ROUND and TRUNC.

      • MONTHS_BETWEEN function returns the count of months between the two dates.

      • ADD_MONTHS function add ”n” number of months to an input date.

      • NEXT_DAY function returns the next day of the date specified.

      • LAST_DAY function returns last day of the month of the input date.

      • ROUND and TRUNC functions are used to round and truncates the date value.

    • Number functions – Accepts numeric input and returns numeric values. Functions under the category are ROUND, TRUNC, and MOD.

      • ROUND and TRUNC functions are used to round and truncate the number value.

      • MOD is used to return the remainder of the division operation between two numbers.

    Illustrations

    General functions

    The SELECT query below demonstrates the use of NVL function.

    SELECT first_name, last_name, salary, NVL (commission_pct,0)
    FROM employees
    WHERE rownum < 5;
    
    FIRST_NAME           LAST_NAME                     SALARY NVL(COMMISSION_PCT,0)
    -------------------- ------------------------- ---------- ---------------------
    Steven               King                           24000                     0
    Neena                Kochhar                        17000                     0
    Lex                  De Haan                        17000                     0
    Alexander            Hunold                          9000                     0
    

    Case Conversion functions

    The SELECT query below demonstrates the use of case conversion functions.

    SELECT UPPER (first_name), INITCAP (last_name), LOWER (job_id)
    FROM employees
    WHERE rownum < 5;
    
    UPPER(FIRST_NAME)    INITCAP(LAST_NAME)        LOWER(JOB_
    -------------------- ------------------------- ----------
    STEVEN               King                      ad_pres
    NEENA                Kochhar                   ad_vp
    LEX                  De Haan                   ad_vp
    ALEXANDER            Hunold                    it_prog
    

    Character functions

    The SELECT query below demonstrates the use of CONCAT function to concatenate two string values.

    SELECT CONCAT (first_name, last_name)
    FROM employees
    WHERE rownum < 5;
    
    CONCAT(FIRST_NAME,LAST_NAME)
    --------------------------------
    EllenAbel
    SundarAnde
    MozheAtkinson
    DavidAustin
    

    The SELECT query below demonstrates the use of SUBSTR and INSTR functions. SUBSTR function returns the portion of input string from 1st position to 5th position. INSTR function returns the numeric position of character ”a” in the first name.

    SELECT SUBSTR (first_name,1,5), INSTR (first_name,''a'')
    FROM employees
    WHERE rownum < 5;
    
    SUBST INSTR(FIRST_NAME,''A'')
    ----- ---------------------
    Ellen                     0
    Sunda                     5
    Mozhe                     0
    David                     2
    

    The SELECT query below demonstrates the usage of LPAD and RPAD to pretty print the employee and job information.

    SELECT RPAD(first_name,10,''_'')||LPAD (job_id,15,''_'')
    FROM employees
    WHERE rownum < 5;
    
    RPAD(FIRST_NAME,10,''_'')||
    -------------------------
    Steven____________AD_PRES
    Neena_______________AD_VP
    Lex_________________AD_VP
    Alexander_________IT_PROG
    

    Number functions

    The SELECT query below demonstrates the use of ROUND and TRUNC functions.

    SELECT ROUND (1372.472,1)
    FROM dual;
    
    ROUND(1372.472,1)
    -----------------
               1372.5
    
    SELECT TRUNC (72183,-2)
    FROM dual;
    
    TRUNC(72183,-2)
    ---------------
              72100
    

    Date arithmetic operations

    The SELECT query below shows a date arithmetic function where difference of employee hire date and sysdate is done.

    SELECT employee_id, (sysdate - hire_date) Employment_days
    FROM employees
    WHERE rownum < 5;
    
    EMPLOYEE_ID EMPLOYMENT_DAYS
    ----------- ---------------
            100      3698.61877
            101      2871.61877
            102      4583.61877
            103      2767.61877
            

    Date functions

    The SELECT query below demonstrates the use of MONTHS_BETWEEN, ADD_MONTHS, NEXT_DAY and LAST_DAY functions.

    SELECT employee_id, MONTHS_BETWEEN (sysdate, hire_date) Employment_months
    FROM employees
    WHERE rownum < 5;
    
    EMPLOYEE_ID EMPLOYMENT_MONTHS
    ----------- -----------------
            100        121.504216
            101        94.3751837
            102        150.633248
            103        90.9558289
    
    SELECT ADD_MONTHS (sysdate, 5), NEXT_DAY (sysdate), LAST_DAY (sysdate)
    FROM dual;
    
    ADD_MONTH NEXT_DAY( LAST_DAY(
    --------- --------- ---------
    01-JAN-14 05-AUG-13 31-AUG-13
    

    Khóa học lập trình tại Toidayhoc vừa học vừa làm dự án vừa nhận lương: Khóa học lập trình nhận lương tại trung tâm Toidayhoc

  • Khóa học miễn phí SQLAlchemy – Discussion nhận dự án làm có lương

    Discuss – SQLAlchemy



    SQLAlchemy is a popular SQL toolkit and Object Relational Mapper. It is written in Python and gives full power and flexibility of SQL to an application developer. It is an open source and cross-platform software released under MIT license. SQLAlchemy is famous for its object-relational mapper (ORM), using which classes can be mapped to the database, thereby allowing the object model and database schema to develop in a cleanly decoupled way from the beginning.


    Khóa học lập trình tại Toidayhoc vừa học vừa làm dự án vừa nhận lương: Khóa học lập trình nhận lương tại trung tâm Toidayhoc

  • Khóa học miễn phí SQLAlchemy – Useful Resources nhận dự án làm có lương

    SQLAlchemy – Useful Resources



    The following resources contain additional information on SQLAlchemy. Please use them to get more in-depth knowledge on this topic.

    Useful Links on SQLAlchemy

    • – A Complete Wikipedia of SQLAlchemy.

    • – SQLAlchemy Official Website

    Useful Books on SQLAlchemy

    To enlist your site on this page, please drop an email to contact@tutorialspoint.com


    Khóa học lập trình tại Toidayhoc vừa học vừa làm dự án vừa nhận lương: Khóa học lập trình nhận lương tại trung tâm Toidayhoc

  • Khóa học miễn phí Deleting Related Objects nhận dự án làm có lương

    SQLAlchemy ORM – Deleting Related Objects



    It is easy to perform delete operation on a single table. All you have to do is to delete an object of the mapped class from a session and commit the action. However, delete operation on multiple related tables is little tricky.

    In our sales.db database, Customer and Invoice classes are mapped to customer and invoice table with one to many type of relationship. We will try to delete Customer object and see the result.

    As a quick reference, below are the definitions of Customer and Invoice classes −

    from sqlalchemy import create_engine, ForeignKey, Column, Integer, String
    engine = create_engine(''sqlite:///sales.db'', echo = True)
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    from sqlalchemy.orm import relationship
    class Customer(Base):
       __tablename__ = ''customers''
    
       id = Column(Integer, primary_key = True)
       name = Column(String)
       address = Column(String)
       email = Column(String)
    
    class Invoice(Base):
       __tablename__ = ''invoices''
    
       id = Column(Integer, primary_key = True)
       custid = Column(Integer, ForeignKey(''customers.id''))
       invno = Column(Integer)
       amount = Column(Integer)
       customer = relationship("Customer", back_populates = "invoices")
    
    Customer.invoices = relationship("Invoice", order_by = Invoice.id, back_populates = "customer")
    

    We setup a session and obtain a Customer object by querying it with primary ID using the below program −

    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind=engine)
    session = Session()
    x = session.query(Customer).get(2)
    

    In our sample table, x.name happens to be ”Gopal Krishna”. Let us delete this x from the session and count the occurrence of this name.

    session.delete(x)
    session.query(Customer).filter_by(name = ''Gopal Krishna'').count()
    

    The resulting SQL expression will return 0.

    SELECT count(*)
    AS count_1
    FROM (
       SELECT customers.id
       AS customers_id, customers.name
       AS customers_name, customers.address
       AS customers_address, customers.email
       AS customers_email
       FROM customers
       WHERE customers.name = ?)
    AS anon_1(''Gopal Krishna'',) 0
    

    However, the related Invoice objects of x are still there. It can be verified by the following code −

    session.query(Invoice).filter(Invoice.invno.in_([10,14])).count()
    

    Here, 10 and 14 are invoice numbers belonging to customer Gopal Krishna. Result of the above query is 2, which means the related objects have not been deleted.

    SELECT count(*)
    AS count_1
    FROM (
       SELECT invoices.id
       AS invoices_id, invoices.custid
       AS invoices_custid, invoices.invno
       AS invoices_invno, invoices.amount
       AS invoices_amount
       FROM invoices
       WHERE invoices.invno IN (?, ?))
    AS anon_1(10, 14) 2
    

    This is because SQLAlchemy doesn’t assume the deletion of cascade; we have to give a command to delete it.

    To change the behavior, we configure cascade options on the User.addresses relationship. Let us close the ongoing session, use new declarative_base() and redeclare the User class, adding in the addresses relationship including the cascade configuration.

    The cascade attribute in relationship function is a comma-separated list of cascade rules which determines how Session operations should be “cascaded” from parent to child. By default, it is False, which means that it is “save-update, merge”.

    The available cascades are as follows −

    • save-update
    • merge
    • expunge
    • delete
    • delete-orphan
    • refresh-expire

    Often used option is “all, delete-orphan” to indicate that related objects should follow along with the parent object in all cases, and be deleted when de-associated.

    Hence redeclared Customer class is shown below −

    class Customer(Base):
       __tablename__ = ''customers''
    
       id = Column(Integer, primary_key = True)
       name = Column(String)
       address = Column(String)
       email = Column(String)
       invoices = relationship(
          "Invoice",
          order_by = Invoice.id,
          back_populates = "customer",
          cascade = "all,
          delete, delete-orphan"
       )
    

    Let us delete the Customer with Gopal Krishna name using the below program and see the count of its related Invoice objects −

    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind = engine)
    session = Session()
    x = session.query(Customer).get(2)
    session.delete(x)
    session.query(Customer).filter_by(name = ''Gopal Krishna'').count()
    session.query(Invoice).filter(Invoice.invno.in_([10,14])).count()
    

    The count is now 0 with following SQL emitted by above script −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE customers.id = ?
    (2,)
    SELECT invoices.id
    AS invoices_id, invoices.custid
    AS invoices_custid, invoices.invno
    AS invoices_invno, invoices.amount
    AS invoices_amount
    FROM invoices
    WHERE ? = invoices.custid
    ORDER BY invoices.id (2,)
    DELETE FROM invoices
    WHERE invoices.id = ? ((1,), (2,))
    DELETE FROM customers
    WHERE customers.id = ? (2,)
    SELECT count(*)
    AS count_1
    FROM (
       SELECT customers.id
       AS customers_id, customers.name
       AS customers_name, customers.address
       AS customers_address, customers.email
       AS customers_email
       FROM customers
       WHERE customers.name = ?)
    AS anon_1(''Gopal Krishna'',)
    SELECT count(*)
    AS count_1
    FROM (
       SELECT invoices.id
       AS invoices_id, invoices.custid
       AS invoices_custid, invoices.invno
       AS invoices_invno, invoices.amount
       AS invoices_amount
       FROM invoices
       WHERE invoices.invno IN (?, ?))
    AS anon_1(10, 14)
    0
    

    Khóa học lập trình tại Toidayhoc vừa học vừa làm dự án vừa nhận lương: Khóa học lập trình nhận lương tại trung tâm Toidayhoc

  • Khóa học miễn phí SQLAlchemy – Quick Guide nhận dự án làm có lương

    SQLAlchemy – Quick Guide



    SQLAlchemy – Introduction

    SQLAlchemy is a popular SQL toolkit and Object Relational Mapper. It is written in Python and gives full power and flexibility of SQL to an application developer. It is an open source and cross-platform software released under MIT license.

    SQLAlchemy is famous for its object-relational mapper (ORM), using which, classes can be mapped to the database, thereby allowing the object model and database schema to develop in a cleanly decoupled way from the beginning.

    As size and performance of SQL databases start to matter, they behave less like object collections. On the other hand, as abstraction in object collections starts to matter, they behave less like tables and rows. SQLAlchemy aims to accommodate both of these principles.

    For this reason, it has adopted the data mapper pattern (like Hibernate) rather than the active record pattern used by a number of other ORMs. Databases and SQL will be viewed in a different perspective using SQLAlchemy.

    Michael Bayer is the original author of SQLAlchemy. Its initial version was released in February 2006. Latest version is numbered as 1.2.7, released as recently as in April 2018.

    What is ORM?

    ORM (Object Relational Mapping) is a programming technique for converting data between incompatible type systems in object-oriented programming languages. Usually, the type system used in an Object Oriented (OO) language like Python contains non-scalar types. These cannot be expressed as primitive types such as integers and strings. Hence, the OO programmer has to convert objects in scalar data to interact with backend database. However, data types in most of the database products such as Oracle, MySQL, etc., are primary.

    In an ORM system, each class maps to a table in the underlying database. Instead of writing tedious database interfacing code yourself, an ORM takes care of these issues for you while you can focus on programming the logics of the system.

    SQLAlchemy – Environment setup

    Let us discuss the environmental setup required to use SQLAlchemy.

    Any version of Python higher than 2.7 is necessary to install SQLAlchemy. The easiest way to install is by using Python Package Manager, pip. This utility is bundled with standard distribution of Python.

    pip install sqlalchemy
    

    Using the above command, we can download the latest released version of SQLAlchemy from and install it to your system.

    In case of anaconda distribution of Python, SQLAlchemy can be installed from conda terminal using the below command −

    conda install -c anaconda sqlalchemy
    

    It is also possible to install SQLAlchemy from below source code −

    python setup.py install
    

    SQLAlchemy is designed to operate with a DBAPI implementation built for a particular database. It uses dialect system to communicate with various types of DBAPI implementations and databases. All dialects require that an appropriate DBAPI driver is installed.

    The following are the dialects included −

    • Firebird
    • Microsoft SQL Server
    • MySQL
    • Oracle
    • PostgreSQL
    • SQLite
    • Sybase

    To check if SQLAlchemy is properly installed and to know its version, enter the following command in the Python prompt −

    >>> import sqlalchemy
    >>>sqlalchemy.__version__
    ''1.2.7''
    

    SQLAlchemy Core – Expression Language

    SQLAlchemy core includes SQL rendering engine, DBAPI integration, transaction integration, and schema description services. SQLAlchemy core uses SQL Expression Language that provides a schema-centric usage paradigm whereas SQLAlchemy ORM is a domain-centric mode of usage.

    The SQL Expression Language presents a system of representing relational database structures and expressions using Python constructs. It presents a system of representing the primitive constructs of the relational database directly without opinion, which is in contrast to ORM that presents a high level and abstracted pattern of usage, which itself is an example of applied usage of the Expression Language.

    Expression Language is one of the core components of SQLAlchemy. It allows the programmer to specify SQL statements in Python code and use it directly in more complex queries. Expression language is independent of backend and comprehensively covers every aspect of raw SQL. It is closer to raw SQL than any other component in SQLAlchemy.

    Expression Language represents the primitive constructs of the relational database directly. Because the ORM is based on top of Expression language, a typical Python database application may have overlapped use of both. The application may use expression language alone, though it has to define its own system of translating application concepts into individual database queries.

    Statements of Expression language will be translated into corresponding raw SQL queries by SQLAlchemy engine. We shall now learn how to create the engine and execute various SQL queries with its help.

    SQLAlchemy Core – Connecting to Database

    In the previous chapter, we have discussed about expression Language in SQLAlchemy. Now let us proceed towards the steps involved in connecting to a database.

    Engine class connects a Pool and Dialect together to provide a source of database connectivity and behavior. An object of Engine class is instantiated using the create_engine() function.

    The create_engine() function takes the database as one argument. The database is not needed to be defined anywhere. The standard calling form has to send the URL as the first positional argument, usually a string that indicates database dialect and connection arguments. Using the code given below, we can create a database.

    >>> from sqlalchemy import create_engine
    >>> engine = create_engine(''sqlite:///college.db'', echo = True)
    

    For a MySQL database, use the below command −

    engine = create_engine("mysql://user:pwd@localhost/college",echo = True)
    

    To specifically mention DB-API to be used for connection, the URL string takes the form as follows −

    dialect[+driver]://user:password@host/dbname
    

    For example, if you are using PyMySQL driver with MySQL, use the following command −

    mysql+pymysql://<username>:<password>@<host>/<dbname>
    

    The echo flag is a shortcut to set up SQLAlchemy logging, which is accomplished via Python’s standard logging module. In the subsequent chapters, we will learn all the generated SQLs. To hide the verbose output, set echo attribute to None. Other arguments to create_engine() function may be dialect specific.

    The create_engine() function returns an Engine object. Some important methods of Engine class are −

    Sr.No. Method & Description
    1

    connect()

    Returns connection object

    2

    execute()

    Executes a SQL statement construct

    3

    begin()

    Returns a context manager delivering a Connection with a Transaction established. Upon successful operation, the Transaction is committed, else it is rolled back

    4

    dispose()

    Disposes of the connection pool used by the Engine

    5

    driver()

    Driver name of the Dialect in use by the Engine

    6

    table_names()

    Returns a list of all table names available in the database

    7

    transaction()

    Executes the given function within a transaction boundary

    SQLAlchemy Core – Creating Table

    Let us now discuss how to use the create table function.

    The SQL Expression Language constructs its expressions against table columns. SQLAlchemy Column object represents a column in a database table which is in turn represented by a Tableobject. Metadata contains definitions of tables and associated objects such as index, view, triggers, etc.

    Hence an object of MetaData class from SQLAlchemy Metadata is a collection of Table objects and their associated schema constructs. It holds a collection of Table objects as well as an optional binding to an Engine or Connection.

    from sqlalchemy import MetaData
    meta = MetaData()
    

    Constructor of MetaData class can have bind and schema parameters which are by default None.

    Next, we define our tables all within above metadata catalog, using the Table construct, which resembles regular SQL CREATE TABLE statement.

    An object of Table class represents corresponding table in a database. The constructor takes the following parameters −

    Name Name of the table
    Metadata MetaData object that will hold this table
    Column(s) One or more objects of column class

    Column object represents a column in a database table. Constructor takes name, type and other parameters such as primary_key, autoincrement and other constraints.

    SQLAlchemy matches Python data to the best possible generic column data types defined in it. Some of the generic data types are −

    • BigInteger
    • Boolean
    • Date
    • DateTime
    • Float
    • Integer
    • Numeric
    • SmallInteger
    • String
    • Text
    • Time

    To create a students table in college database, use the following snippet −

    from sqlalchemy import Table, Column, Integer, String, MetaData
    meta = MetaData()
    
    students = Table(
       ''students'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''name'', String),
       Column(''lastname'', String),
    )
    

    The create_all() function uses the engine object to create all the defined table objects and stores the information in metadata.

    meta.create_all(engine)
    

    Complete code is given below which will create a SQLite database college.db with a students table in it.

    from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
    engine = create_engine(''sqlite:///college.db'', echo = True)
    meta = MetaData()
    
    students = Table(
       ''students'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''name'', String),
       Column(''lastname'', String),
    )
    meta.create_all(engine)
    

    Because echo attribute of create_engine() function is set to True, the console will display the actual SQL query for table creation as follows −

    CREATE TABLE students (
       id INTEGER NOT NULL,
       name VARCHAR,
       lastname VARCHAR,
       PRIMARY KEY (id)
    )
    

    The college.db will be created in current working directory. To check if the students table is created, you can open the database using any SQLite GUI tool such as SQLiteStudio.

    The below image shows the students table that is created in the database −

    Students Table

    SQLAlchemy Core – SQL Expressions

    In this chapter, we will briefly focus on the SQL Expressions and their functions.

    SQL expressions are constructed using corresponding methods relative to target table object. For example, the INSERT statement is created by executing insert() method as follows −

    ins = students.insert()
    

    The result of above method is an insert object that can be verified by using str() function. The below code inserts details like student id, name, lastname.

    ''INSERT INTO students (id, name, lastname) VALUES (:id, :name, :lastname)''
    

    It is possible to insert value in a specific field by values() method to insert object. The code for the same is given below −

    >>> ins = users.insert().values(name = ''Karan'')
    >>> str(ins)
    ''INSERT INTO users (name) VALUES (:name)''
    

    The SQL echoed on Python console doesn’t show the actual value (‘Karan’ in this case). Instead, SQLALchemy generates a bind parameter which is visible in compiled form of the statement.

    ins.compile().params
    {''name'': ''Karan''}
    

    Similarly, methods like update(), delete() and select() create UPDATE, DELETE and SELECT expressions respectively. We shall learn about them in later chapters.

    SQLAlchemy Core – Executing Expression

    In the previous chapter, we have learnt SQL Expressions. In this chapter, we shall look into the execution of these expressions.

    In order to execute the resulting SQL expressions, we have to obtain a connection object representing an actively checked out DBAPI connection resource and then feed the expression object as shown in the code below.

    conn = engine.connect()
    

    The following insert() object can be used for execute() method −

    ins = students.insert().values(name = ''Ravi'', lastname = ''Kapoor'')
    result = conn.execute(ins)
    

    The console shows the result of execution of SQL expression as below −

    INSERT INTO students (name, lastname) VALUES (?, ?)
    (''Ravi'', ''Kapoor'')
    COMMIT
    

    Following is the entire snippet that shows the execution of INSERT query using SQLAlchemy’s core technique −

    from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
    engine = create_engine(''sqlite:///college.db'', echo = True)
    meta = MetaData()
    
    students = Table(
       ''students'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''name'', String),
       Column(''lastname'', String),
    )
    
    ins = students.insert()
    ins = students.insert().values(name = ''Ravi'', lastname = ''Kapoor'')
    conn = engine.connect()
    result = conn.execute(ins)
    

    The result can be verified by opening the database using SQLite Studio as shown in the below screenshot −

    SQLite Studio

    The result variable is known as a object. It is analogous to the DBAPI cursor object. We can acquire information about the primary key values which were generated from our statement using ResultProxy.inserted_primary_key as shown below −

    result.inserted_primary_key
    [1]
    

    To issue many inserts using DBAPI’s execute many() method, we can send in a list of dictionaries each containing a distinct set of parameters to be inserted.

    conn.execute(students.insert(), [
       {''name'':''Rajiv'', ''lastname'' : ''Khanna''},
       {''name'':''Komal'',''lastname'' : ''Bhandari''},
       {''name'':''Abdul'',''lastname'' : ''Sattar''},
       {''name'':''Priya'',''lastname'' : ''Rajhans''},
    ])
    

    This is reflected in the data view of the table as shown in the following figure −

     Table Data View

    SQLAlchemy Core – Selecting Rows

    In this chapter, we will discuss about the concept of selecting rows in the table object.

    The select() method of table object enables us to construct SELECT expression.

    s = students.select()
    

    The select object translates to SELECT query by str(s) function as shown below −

    ''SELECT students.id, students.name, students.lastname FROM students''
    

    We can use this select object as a parameter to execute() method of connection object as shown in the code below −

    result = conn.execute(s)
    

    When the above statement is executed, Python shell echoes following equivalent SQL expression −

    SELECT students.id, students.name, students.lastname
    FROM students
    

    The resultant variable is an equivalent of cursor in DBAPI. We can now fetch records using fetchone() method.

    row = result.fetchone()
    

    All selected rows in the table can be printed by a for loop as given below −

    for row in result:
       print (row)
    

    The complete code to print all rows from students table is shown below −

    from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
    engine = create_engine(''sqlite:///college.db'', echo = True)
    meta = MetaData()
    
    students = Table(
       ''students'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''name'', String),
       Column(''lastname'', String),
    )
    
    s = students.select()
    conn = engine.connect()
    result = conn.execute(s)
    
    for row in result:
       print (row)
    

    The output shown in Python shell is as follows −

    (1, ''Ravi'', ''Kapoor'')
    (2, ''Rajiv'', ''Khanna'')
    (3, ''Komal'', ''Bhandari'')
    (4, ''Abdul'', ''Sattar'')
    (5, ''Priya'', ''Rajhans'')
    

    The WHERE clause of SELECT query can be applied by using Select.where(). For example, if we want to display rows with id >2

    s = students.select().where(students.c.id>2)
    result = conn.execute(s)
    
    for row in result:
       print (row)
    

    Here c attribute is an alias for column. Following output will be displayed on the shell −

    (3, ''Komal'', ''Bhandari'')
    (4, ''Abdul'', ''Sattar'')
    (5, ''Priya'', ''Rajhans'')
    

    Here, we have to note that select object can also be obtained by select() function in sqlalchemy.sql module. The select() function requires the table object as argument.

    from sqlalchemy.sql import select
    s = select([users])
    result = conn.execute(s)
    

    SQLAlchemy Core – Using Textual SQL

    SQLAlchemy lets you just use strings, for those cases when the SQL is already known and there isn’t a strong need for the statement to support dynamic features. The text() construct is used to compose a textual statement that is passed to the database mostly unchanged.

    It constructs a new TextClause, representing a textual SQL string directly as shown in the below code −

    from sqlalchemy import text
    t = text("SELECT * FROM students")
    result = connection.execute(t)
    

    The advantages text() provides over a plain string are −

    • backend-neutral support for bind parameters
    • per-statement execution options
    • result-column typing behaviour

    The text()function requires Bound parameters in the named colon format. They are consistent regardless of database backend. To send values in for the parameters, we pass them into the execute() method as additional arguments.

    The following example uses bound parameters in textual SQL −

    from sqlalchemy.sql import text
    s = text("select students.name, students.lastname from students where students.name between :x and :y")
    conn.execute(s, x = ''A'', y = ''L'').fetchall()
    

    The text() function constructs SQL expression as follows −

    select students.name, students.lastname from students where students.name between ? and ?
    

    The values of x = ’A’ and y = ’L’ are passed as parameters. Result is a list of rows with names between ‘A’ and ‘L’ −

    [(''Komal'', ''Bhandari''), (''Abdul'', ''Sattar'')]
    

    The text() construct supports pre-established bound values using the TextClause.bindparams() method. The parameters can also be explicitly typed as follows −

    stmt = text("SELECT * FROM students WHERE students.name BETWEEN :x AND :y")
    
    stmt = stmt.bindparams(
       bindparam("x", type_= String),
       bindparam("y", type_= String)
    )
    
    result = conn.execute(stmt, {"x": "A", "y": "L"})
    
    The text() function also be produces fragments of SQL within a select() object that
    accepts text() objects as an arguments. The “geometry” of the statement is provided by
    select() construct , and the textual content by text() construct. We can build a statement
    without the need to refer to any pre-established Table metadata.
    
    from sqlalchemy.sql import select
    s = select([text("students.name, students.lastname from students")]).where(text("students.name between :x and :y"))
    conn.execute(s, x = ''A'', y = ''L'').fetchall()
    

    You can also use and_() function to combine multiple conditions in WHERE clause created with the help of text() function.

    from sqlalchemy import and_
    from sqlalchemy.sql import select
    s = select([text("* from students")])
    .where(
       and_(
          text("students.name between :x and :y"),
          text("students.id>2")
       )
    )
    conn.execute(s, x = ''A'', y = ''L'').fetchall()
    

    Above code fetches rows with names between “A” and “L” with id greater than 2. The output of the code is given below −

    [(3, ''Komal'', ''Bhandari''), (4, ''Abdul'', ''Sattar'')]
    

    SQLAlchemy Core – Using Aliases

    The alias in SQL corresponds to a “renamed” version of a table or SELECT statement, which occurs anytime you say “SELECT * FROM table1 AS a”. The AS creates a new name for the table. Aliases allow any table or subquery to be referenced by a unique name.

    In case of a table, this allows the same table to be named in the FROM clause multiple times. It provides a parent name for the columns represented by the statement, allowing them to be referenced relative to this name.

    In SQLAlchemy, any Table, select() construct, or other selectable object can be turned into an alias using the From Clause.alias() method, which produces an Alias construct. The alias() function in sqlalchemy.sql module represents an alias, as typically applied to any table or sub-select within a SQL statement using the AS keyword.

    from sqlalchemy.sql import alias
    st = students.alias("a")
    

    This alias can now be used in select() construct to refer to students table −

    s = select([st]).where(st.c.id>2)
    

    This translates to SQL expression as follows −

    SELECT a.id, a.name, a.lastname FROM students AS a WHERE a.id > 2
    

    We can now execute this SQL query with the execute() method of connection object. The complete code is as follows −

    from sqlalchemy.sql import alias, select
    st = students.alias("a")
    s = select([st]).where(st.c.id > 2)
    conn.execute(s).fetchall()
    

    When above line of code is executed, it generates the following output −

    [(3, ''Komal'', ''Bhandari''), (4, ''Abdul'', ''Sattar''), (5, ''Priya'', ''Rajhans'')]
    

    Using UPDATE Expression

    The update() method on target table object constructs equivalent UPDATE SQL expression.

    table.update().where(conditions).values(SET expressions)
    

    The values() method on the resultant update object is used to specify the SET conditions of the UPDATE. If left as None, the SET conditions are determined from those parameters passed to the statement during the execution and/or compilation of the statement.

    The where clause is an Optional expression describing the WHERE condition of the UPDATE statement.

    Following code snippet changes value of ‘lastname’ column from ‘Khanna’ to ‘Kapoor’ in students table −

    stmt = students.update().where(students.c.lastname == ''Khanna'').values(lastname = ''Kapoor'')
    

    The stmt object is an update object that translates to −

    ''UPDATE students SET lastname = :lastname WHERE students.lastname = :lastname_1''
    

    The bound parameter lastname_1 will be substituted when execute() method is invoked. The complete update code is given below −

    from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
    engine = create_engine(''sqlite:///college.db'', echo = True)
    meta = MetaData()
    
    students = Table(
       ''students'',
       meta,
       Column(''id'', Integer, primary_key = True),
       Column(''name'', String),
       Column(''lastname'', String),
    )
    
    conn = engine.connect()
    stmt=students.update().where(students.c.lastname==''Khanna'').values(lastname=''Kapoor'')
    conn.execute(stmt)
    s = students.select()
    conn.execute(s).fetchall()
    

    The above code displays following output with second row showing effect of update operation as in the screenshot given −

    [
       (1, ''Ravi'', ''Kapoor''),
       (2, ''Rajiv'', ''Kapoor''),
       (3, ''Komal'', ''Bhandari''),
       (4, ''Abdul'', ''Sattar''),
       (5, ''Priya'', ''Rajhans'')
    ]
    

    Update Operation

    Note that similar functionality can also be achieved by using update() function in sqlalchemy.sql.expression module as shown below −

    from sqlalchemy.sql.expression import update
    stmt = update(students).where(students.c.lastname == ''Khanna'').values(lastname = ''Kapoor'')
    

    Using DELETE Expression

    In the previous chapter, we have understood what an Update expression does. The next expression that we are going to learn is Delete.

    The delete operation can be achieved by running delete() method on target table object as given in the following statement −

    stmt = students.delete()
    

    In case of students table, the above line of code constructs a SQL expression as following −

    ''DELETE FROM students''
    

    However, this will delete all rows in students table. Usually DELETE query is associated with a logical expression specified by WHERE clause. The following statement shows where parameter −

    stmt = students.delete().where(students.c.id > 2)
    

    The resultant SQL expression will have a bound parameter which will be substituted at runtime when the statement is executed.

    ''DELETE FROM students WHERE students.id > :id_1''
    

    Following code example will delete those rows from students table having lastname as ‘Khanna’ −

    from sqlalchemy.sql.expression import update
    from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
    engine = create_engine(''sqlite:///college.db'', echo = True)
    
    meta = MetaData()
    
    students = Table(
       ''students'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''name'', String),
       Column(''lastname'', String),
    )
    
    conn = engine.connect()
    stmt = students.delete().where(students.c.lastname == ''Khanna'')
    conn.execute(stmt)
    s = students.select()
    conn.execute(s).fetchall()
    

    To verify the result, refresh the data view of students table in SQLiteStudio.

    SQLAlchemy Core – Using Multiple Tables

    One of the important features of RDBMS is establishing relation between tables. SQL operations like SELECT, UPDATE and DELETE can be performed on related tables. This section describes these operations using SQLAlchemy.

    For this purpose, two tables are created in our SQLite database (college.db). The students table has the same structure as given in the previous section; whereas the addresses table has st_id column which is mapped to id column in students table using foreign key constraint.

    The following code will create two tables in college.db −

    from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, ForeignKey
    engine = create_engine(''sqlite:///college.db'', echo=True)
    meta = MetaData()
    
    students = Table(
       ''students'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''name'', String),
       Column(''lastname'', String),
    )
    
    addresses = Table(
       ''addresses'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''st_id'', Integer, ForeignKey(''students.id'')),
       Column(''postal_add'', String),
       Column(''email_add'', String))
    
    meta.create_all(engine)
    

    Above code will translate to CREATE TABLE queries for students and addresses table as below −

    CREATE TABLE students (
       id INTEGER NOT NULL,
       name VARCHAR,
       lastname VARCHAR,
       PRIMARY KEY (id)
    )
    
    CREATE TABLE addresses (
       id INTEGER NOT NULL,
       st_id INTEGER,
       postal_add VARCHAR,
       email_add VARCHAR,
       PRIMARY KEY (id),
       FOREIGN KEY(st_id) REFERENCES students (id)
    )
    

    The following screenshots present the above code very clearly −

    CREATE TABLE Queries

    Addresses Table Queries

    These tables are populated with data by executing insert() method of table objects. To insert 5 rows in students table, you can use the code given below −

    from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
    engine = create_engine(''sqlite:///college.db'', echo = True)
    meta = MetaData()
    
    conn = engine.connect()
    students = Table(
       ''students'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''name'', String),
       Column(''lastname'', String),
    )
    
    conn.execute(students.insert(), [
       {''name'':''Ravi'', ''lastname'':''Kapoor''},
       {''name'':''Rajiv'', ''lastname'' : ''Khanna''},
       {''name'':''Komal'',''lastname'' : ''Bhandari''},
       {''name'':''Abdul'',''lastname'' : ''Sattar''},
       {''name'':''Priya'',''lastname'' : ''Rajhans''},
    ])
    

    Rows are added in addresses table with the help of the following code −

    from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
    engine = create_engine(''sqlite:///college.db'', echo = True)
    meta = MetaData()
    conn = engine.connect()
    
    addresses = Table(
       ''addresses'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''st_id'', Integer),
       Column(''postal_add'', String),
       Column(''email_add'', String)
    )
    
    conn.execute(addresses.insert(), [
       {''st_id'':1, ''postal_add'':''Shivajinagar Pune'', ''email_add'':''ravi@gmail.com''},
       {''st_id'':1, ''postal_add'':''ChurchGate Mumbai'', ''email_add'':''kapoor@gmail.com''},
       {''st_id'':3, ''postal_add'':''Jubilee Hills Hyderabad'', ''email_add'':''komal@gmail.com''},
       {''st_id'':5, ''postal_add'':''MG Road Bangaluru'', ''email_add'':''as@yahoo.com''},
       {''st_id'':2, ''postal_add'':''Cannought Place new Delhi'', ''email_add'':''admin@khanna.com''},
    ])
    

    Note that the st_id column in addresses table refers to id column in students table. We can now use this relation to fetch data from both the tables. We want to fetch name and lastname from students table corresponding to st_id in the addresses table.

    from sqlalchemy.sql import select
    s = select([students, addresses]).where(students.c.id == addresses.c.st_id)
    result = conn.execute(s)
    
    for row in result:
       print (row)
    

    The select objects will effectively translate into following SQL expression joining two tables on common relation −

    SELECT students.id,
       students.name,
       students.lastname,
       addresses.id,
       addresses.st_id,
       addresses.postal_add,
       addresses.email_add
    FROM students, addresses
    WHERE students.id = addresses.st_id
    

    This will produce output extracting corresponding data from both tables as follows −

    (1, ''Ravi'', ''Kapoor'', 1, 1, ''Shivajinagar Pune'', ''ravi@gmail.com'')
    (1, ''Ravi'', ''Kapoor'', 2, 1, ''ChurchGate Mumbai'', ''kapoor@gmail.com'')
    (3, ''Komal'', ''Bhandari'', 3, 3, ''Jubilee Hills Hyderabad'', ''komal@gmail.com'')
    (5, ''Priya'', ''Rajhans'', 4, 5, ''MG Road Bangaluru'', ''as@yahoo.com'')
    (2, ''Rajiv'', ''Khanna'', 5, 2, ''Cannought Place new Delhi'', ''admin@khanna.com'')
    

    Using Multiple Table Updates

    In the previous chapter, we have discussed about how to use multiple tables. So we proceed a step further and learn multiple table updates in this chapter.

    Using SQLAlchemy’s table object, more than one table can be specified in WHERE clause of update() method. The PostgreSQL and Microsoft SQL Server support UPDATE statements that refer to multiple tables. This implements “UPDATE FROM” syntax, which updates one table at a time. However, additional tables can be referenced in an additional “FROM” clause in the WHERE clause directly. The following lines of codes explain the concept of multiple table updates clearly.

    stmt = students.update().
    values({
       students.c.name:''xyz'',
       addresses.c.email_add:''abc@xyz.com''
    }).
    where(students.c.id == addresses.c.id)
    

    The update object is equivalent to the following UPDATE query −

    UPDATE students
    SET email_add = :addresses_email_add, name = :name
    FROM addresses
    WHERE students.id = addresses.id
    

    As far as MySQL dialect is concerned, multiple tables can be embedded into a single UPDATE statement separated by a comma as given below −

    stmt = students.update().
       values(name = ''xyz'').
       where(students.c.id == addresses.c.id)
    

    The following code depicts the resulting UPDATE query −

    ''UPDATE students SET name = :name
    FROM addresses
    WHERE students.id = addresses.id''
    

    SQLite dialect however doesn’t support multiple-table criteria within UPDATE and shows following error −

    NotImplementedError: This backend does not support multiple-table criteria within UPDATE
    

    Parameter-Ordered Updates

    The UPDATE query of raw SQL has SET clause. It is rendered by the update() construct using the column ordering given in the originating Table object. Therefore, a particular UPDATE statement with particular columns will be rendered the same each time. Since the parameters themselves are passed to the Update.values() method as Python dictionary keys, there is no other fixed ordering available.

    In some cases, the order of parameters rendered in the SET clause are significant. In MySQL, providing updates to column values is based on that of other column values.

    Following statement’s result −

    UPDATE table1 SET x = y + 10, y = 20
    

    will have a different result than −

    UPDATE table1 SET y = 20, x = y + 10
    

    SET clause in MySQL is evaluated on a per-value basis and not on per-row basis. For this purpose, the preserve_parameter_order is used. Python list of 2-tuples is given as argument to the Update.values() method −

    stmt = table1.update(preserve_parameter_order = True).
       values([(table1.c.y, 20), (table1.c.x, table1.c.y + 10)])
    

    The List object is similar to dictionary except that it is ordered. This ensures that the “y” column’s SET clause will render first, then the “x” column’s SET clause.

    SQLAlchemy Core – Multiple Table Deletes

    In this chapter, we will look into the Multiple Table Deletes expression which is similar to using Multiple Table Updates function.

    More than one table can be referred in WHERE clause of DELETE statement in many DBMS dialects. For PG and MySQL, “DELETE USING” syntax is used; and for SQL Server, using “DELETE FROM” expression refers to more than one table. The SQLAlchemy delete() construct supports both of these modes implicitly, by specifying multiple tables in the WHERE clause as follows −

    stmt = users.delete().
       where(users.c.id == addresses.c.id).
       where(addresses.c.email_address.startswith(''xyz%''))
    conn.execute(stmt)
    

    On a PostgreSQL backend, the resulting SQL from the above statement would render as −

    DELETE FROM users USING addresses
    WHERE users.id = addresses.id
    AND (addresses.email_address LIKE %(email_address_1)s || ''%%'')
    

    If this method is used with a database that doesn’t support this behaviour, the compiler will raise NotImplementedError.

    SQLAlchemy Core – Using Joins

    In this chapter, we will learn how to use Joins in SQLAlchemy.

    Effect of joining is achieved by just placing two tables in either the columns clause or the where clause of the select() construct. Now we use the join() and outerjoin() methods.

    The join() method returns a join object from one table object to another.

    join(right, onclause = None, isouter = False, full = False)
    

    The functions of the parameters mentioned in the above code are as follows −

    • right − the right side of the join; this is any Table object

    • onclause − a SQL expression representing the ON clause of the join. If left at None, it attempts to join the two tables based on a foreign key relationship

    • isouter − if True, renders a LEFT OUTER JOIN, instead of JOIN

    • full − if True, renders a FULL OUTER JOIN, instead of LEFT OUTER JOIN

    For example, following use of join() method will automatically result in join based on the foreign key.

    >>> print(students.join(addresses))
    

    This is equivalent to following SQL expression −

    students JOIN addresses ON students.id = addresses.st_id
    

    You can explicitly mention joining criteria as follows −

    j = students.join(addresses, students.c.id == addresses.c.st_id)
    

    If we now build the below select construct using this join as −

    stmt = select([students]).select_from(j)
    

    This will result in following SQL expression −

    SELECT students.id, students.name, students.lastname
    FROM students JOIN addresses ON students.id = addresses.st_id
    

    If this statement is executed using the connection representing engine, data belonging to selected columns will be displayed. The complete code is as follows −

    from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, ForeignKey
    engine = create_engine(''sqlite:///college.db'', echo = True)
    
    meta = MetaData()
    conn = engine.connect()
    students = Table(
       ''students'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''name'', String),
       Column(''lastname'', String),
    )
    
    addresses = Table(
       ''addresses'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''st_id'', Integer,ForeignKey(''students.id'')),
       Column(''postal_add'', String),
       Column(''email_add'', String)
    )
    
    from sqlalchemy import join
    from sqlalchemy.sql import select
    j = students.join(addresses, students.c.id == addresses.c.st_id)
    stmt = select([students]).select_from(j)
    result = conn.execute(stmt)
    result.fetchall()
    

    The following is the output of the above code −

    [
       (1, ''Ravi'', ''Kapoor''),
       (1, ''Ravi'', ''Kapoor''),
       (3, ''Komal'', ''Bhandari''),
       (5, ''Priya'', ''Rajhans''),
       (2, ''Rajiv'', ''Khanna'')
    ]
    

    SQLAlchemy Core – Using Conjunctions

    Conjunctions are functions in SQLAlchemy module that implement relational operators used in WHERE clause of SQL expressions. The operators AND, OR, NOT, etc., are used to form a compound expression combining two individual logical expressions. A simple example of using AND in SELECT statement is as follows −

    SELECT * from EMPLOYEE WHERE salary>10000 AND age>30
    

    SQLAlchemy functions and_(), or_() and not_() respectively implement AND, OR and NOT operators.

    and_() function

    It produces a conjunction of expressions joined by AND. An example is given below for better understanding −

    from sqlalchemy import and_
    
    print(
       and_(
          students.c.name == ''Ravi'',
          students.c.id <3
       )
    )
    

    This translates to −

    students.name = :name_1 AND students.id < :id_1
    

    To use and_() in a select() construct on a students table, use the following line of code −

    stmt = select([students]).where(and_(students.c.name == ''Ravi'', students.c.id <3))
    

    SELECT statement of the following nature will be constructed −

    SELECT students.id,
       students.name,
       students.lastname
    FROM students
    WHERE students.name = :name_1 AND students.id < :id_1
    

    The complete code that displays output of the above SELECT query is as follows −

    from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, ForeignKey, select
    engine = create_engine(''sqlite:///college.db'', echo = True)
    meta = MetaData()
    conn = engine.connect()
    
    students = Table(
       ''students'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''name'', String),
       Column(''lastname'', String),
    )
    
    from sqlalchemy import and_, or_
    stmt = select([students]).where(and_(students.c.name == ''Ravi'', students.c.id <3))
    result = conn.execute(stmt)
    print (result.fetchall())
    

    Following row will be selected assuming that students table is populated with data used in previous example −

    [(1, ''Ravi'', ''Kapoor'')]
    

    or_() function

    It produces conjunction of expressions joined by OR. We shall replace the stmt object in the above example with the following one using or_()

    stmt = select([students]).where(or_(students.c.name == ''Ravi'', students.c.id <3))
    

    Which will be effectively equivalent to following SELECT query −

    SELECT students.id,
       students.name,
       students.lastname
    FROM students
    WHERE students.name = :name_1
    OR students.id < :id_1
    

    Once you make the substitution and run the above code, the result will be two rows falling in the OR condition −

    [(1, ''Ravi'', ''Kapoor''),
    (2, ''Rajiv'', ''Khanna'')]
    

    asc() function

    It produces an ascending ORDER BY clause. The function takes the column to apply the function as a parameter.

    from sqlalchemy import asc
    stmt = select([students]).order_by(asc(students.c.name))
    

    The statement implements following SQL expression −

    SELECT students.id,
       students.name,
       students.lastname
    FROM students
    ORDER BY students.name ASC
    

    Following code lists out all records in students table in ascending order of name column −

    from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, ForeignKey, select
    engine = create_engine(''sqlite:///college.db'', echo = True)
    meta = MetaData()
    conn = engine.connect()
    
    students = Table(
       ''students'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''name'', String),
       Column(''lastname'', String),
    )
    
    from sqlalchemy import asc
    stmt = select([students]).order_by(asc(students.c.name))
    result = conn.execute(stmt)
    
    for row in result:
       print (row)
    

    Above code produces following output −

    (4, ''Abdul'', ''Sattar'')
    (3, ''Komal'', ''Bhandari'')
    (5, ''Priya'', ''Rajhans'')
    (2, ''Rajiv'', ''Khanna'')
    (1, ''Ravi'', ''Kapoor'')
    

    desc() function

    Similarly desc() function produces descending ORDER BY clause as follows −

    from sqlalchemy import desc
    stmt = select([students]).order_by(desc(students.c.lastname))
    

    The equivalent SQL expression is −

    SELECT students.id,
       students.name,
       students.lastname
    FROM students
    ORDER BY students.lastname DESC
    

    And the output for the above lines of code is −

    (4, ''Abdul'', ''Sattar'')
    (5, ''Priya'', ''Rajhans'')
    (2, ''Rajiv'', ''Khanna'')
    (1, ''Ravi'', ''Kapoor'')
    (3, ''Komal'', ''Bhandari'')
    

    between() function

    It produces a BETWEEN predicate clause. This is generally used to validate if value of a certain column falls between a range. For example, following code selects rows for which id column is between 2 and 4 −

    from sqlalchemy import between
    stmt = select([students]).where(between(students.c.id,2,4))
    print (stmt)
    

    The resulting SQL expression resembles −

    SELECT students.id,
       students.name,
       students.lastname
    FROM students
    WHERE students.id
    BETWEEN :id_1 AND :id_2
    

    and the result is as follows −

    (2, ''Rajiv'', ''Khanna'')
    (3, ''Komal'', ''Bhandari'')
    (4, ''Abdul'', ''Sattar'')
    

    SQLAlchemy Core – Using Functions

    Some of the important functions used in SQLAlchemy are discussed in this chapter.

    Standard SQL has recommended many functions which are implemented by most dialects. They return a single value based on the arguments passed to it. Some SQL functions take columns as arguments whereas some are generic. Thefunc keyword in SQLAlchemy API is used to generate these functions.

    In SQL, now() is a generic function. Following statements renders the now() function using func −

    from sqlalchemy.sql import func
    result = conn.execute(select([func.now()]))
    print (result.fetchone())
    

    Sample result of above code may be as shown below −

    (datetime.datetime(2018, 6, 16, 6, 4, 40),)
    

    On the other hand, count() function which returns number of rows selected from a table, is rendered by following usage of func −

    from sqlalchemy.sql import func
    result = conn.execute(select([func.count(students.c.id)]))
    print (result.fetchone())
    

    From the above code, count of number of rows in students table will be fetched.

    Some built-in SQL functions are demonstrated using Employee table with following data −

    ID Name Marks
    1 Kamal 56
    2 Fernandez 85
    3 Sunil 62
    4 Bhaskar 76

    The max() function is implemented by following usage of func from SQLAlchemy which will result in 85, the total maximum marks obtained −

    from sqlalchemy.sql import func
    result = conn.execute(select([func.max(employee.c.marks)]))
    print (result.fetchone())
    

    Similarly, min() function that will return 56, minimum marks, will be rendered by following code −

    from sqlalchemy.sql import func
    result = conn.execute(select([func.min(employee.c.marks)]))
    print (result.fetchone())
    

    So, the AVG() function can also be implemented by using the below code −

    from sqlalchemy.sql import func
    result = conn.execute(select([func.avg(employee.c.marks)]))
    print (result.fetchone())
    
    Functions are normally used in the columns clause of a select statement.
    They can also be given label as well as a type. A label to function allows the result
    to be targeted in a result row based on a string name, and a type is required when
    you need result-set processing to occur.from sqlalchemy.sql import func
    
    result = conn.execute(select([func.max(students.c.lastname).label(''Name'')]))
    
    print (result.fetchone())
    

    SQLAlchemy Core – Using Set Operations

    In the last chapter, we have learnt about various functions such as max(), min(), count(), etc., here, we will learn about set operations and their uses.

    Set operations such as UNION and INTERSECT are supported by standard SQL and most of its dialect. SQLAlchemy implements them with the help of following functions −

    union()

    While combining results of two or more SELECT statements, UNION eliminates duplicates from the resultset. The number of columns and datatype must be same in both the tables.

    The union() function returns a CompoundSelect object from multiple tables. Following example demonstrates its use −

    from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, union
    engine = create_engine(''sqlite:///college.db'', echo = True)
    
    meta = MetaData()
    conn = engine.connect()
    addresses = Table(
       ''addresses'', meta,
       Column(''id'', Integer, primary_key = True),
       Column(''st_id'', Integer),
       Column(''postal_add'', String),
       Column(''email_add'', String)
    )
    
    u = union(addresses.select().where(addresses.c.email_add.like(''%@gmail.com addresses.select().where(addresses.c.email_add.like(''%@yahoo.com''))))
    
    result = conn.execute(u)
    result.fetchall()
    

    The union construct translates to following SQL expression −

    SELECT addresses.id,
       addresses.st_id,
       addresses.postal_add,
       addresses.email_add
    FROM addresses
    WHERE addresses.email_add LIKE ? UNION SELECT addresses.id,
       addresses.st_id,
       addresses.postal_add,
       addresses.email_add
    FROM addresses
    WHERE addresses.email_add LIKE ?
    

    From our addresses table, following rows represent the union operation −

    [
       (1, 1, ''Shivajinagar Pune'', ''ravi@gmail.com''),
       (2, 1, ''ChurchGate Mumbai'', ''kapoor@gmail.com''),
       (3, 3, ''Jubilee Hills Hyderabad'', ''komal@gmail.com''),
       (4, 5, ''MG Road Bangaluru'', ''as@yahoo.com'')
    ]
    

    union_all()

    UNION ALL operation cannot remove the duplicates and cannot sort the data in the resultset. For example, in above query, UNION is replaced by UNION ALL to see the effect.

    u = union_all(addresses.select().where(addresses.c.email_add.like(''%@gmail.com'')), addresses.select().where(addresses.c.email_add.like(''%@yahoo.com'')))
    

    The corresponding SQL expression is as follows −

    SELECT addresses.id,
       addresses.st_id,
       addresses.postal_add,
       addresses.email_add
    FROM addresses
    WHERE addresses.email_add LIKE ? UNION ALL SELECT addresses.id,
       addresses.st_id,
       addresses.postal_add,
       addresses.email_add
    FROM addresses
    WHERE addresses.email_add LIKE ?
    

    except_()

    The SQL EXCEPT clause/operator is used to combine two SELECT statements and return rows from the first SELECT statement that are not returned by the second SELECT statement. The except_() function generates a SELECT expression with EXCEPT clause.

    In the following example, the except_() function returns only those records from addresses table that have ‘gmail.com’ in email_add field but excludes those which have ‘Pune’ as part of postal_add field.

    u = except_(addresses.select().where(addresses.c.email_add.like(''%@gmail.com'')), addresses.select().where(addresses.c.postal_add.like(''%Pune'')))
    

    Result of the above code is the following SQL expression −

    SELECT addresses.id,
       addresses.st_id,
       addresses.postal_add,
       addresses.email_add
    FROM addresses
    WHERE addresses.email_add LIKE ? EXCEPT SELECT addresses.id,
       addresses.st_id,
       addresses.postal_add,
       addresses.email_add
    FROM addresses
    WHERE addresses.postal_add LIKE ?
    

    Assuming that addresses table contains data used in earlier examples, it will display following output −

    [(2, 1, ''ChurchGate Mumbai'', ''kapoor@gmail.com''),
       (3, 3, ''Jubilee Hills Hyderabad'', ''komal@gmail.com'')]
    

    intersect()

    Using INTERSECT operator, SQL displays common rows from both the SELECT statements. The intersect() function implements this behaviour.

    In following examples, two SELECT constructs are parameters to intersect() function. One returns rows containing ‘gmail.com’ as part of email_add column, and other returns rows having ‘Pune’ as part of postal_add column. The result will be common rows from both resultsets.

    u = intersect(addresses.select().where(addresses.c.email_add.like(''%@gmail.com'')), addresses.select().where(addresses.c.postal_add.like(''%Pune'')))
    

    In effect, this is equivalent to following SQL statement −

    SELECT addresses.id,
       addresses.st_id,
       addresses.postal_add,
       addresses.email_add
    FROM addresses
    WHERE addresses.email_add LIKE ? INTERSECT SELECT addresses.id,
       addresses.st_id,
       addresses.postal_add,
       addresses.email_add
    FROM addresses
    WHERE addresses.postal_add LIKE ?
    

    The two bound parameters ‘%gmail.com’ and ‘%Pune’ generate a single row from original data in addresses table as shown below −

    [(1, 1, ''Shivajinagar Pune'', ''ravi@gmail.com'')]
    

    SQLAlchemy ORM – Declaring Mapping

    The main objective of the Object Relational Mapper API of SQLAlchemy is to facilitate associating user-defined Python classes with database tables, and objects of those classes with rows in their corresponding tables. Changes in states of objects and rows are synchronously matched with each other. SQLAlchemy enables expressing database queries in terms of user defined classes and their defined relationships.

    The ORM is constructed on top of the SQL Expression Language. It is a high level and abstracted pattern of usage. In fact, ORM is an applied usage of the Expression Language.

    Although a successful application may be constructed using the Object Relational Mapper exclusively, sometimes an application constructed with the ORM may use the Expression Language directly where specific database interactions are required.

    Declare Mapping

    First of all, create_engine() function is called to set up an engine object which is subsequently used to perform SQL operations. The function has two arguments, one is the name of database and other is an echo parameter when set to True will generate the activity log. If it doesn’t exist, the database will be created. In the following example, a SQLite database is created.

    from sqlalchemy import create_engine
    engine = create_engine(''sqlite:///sales.db'', echo = True)
    

    The Engine establishes a real DBAPI connection to the database when a method like Engine.execute() or Engine.connect() is called. It is then used to emit the SQLORM which does not use the Engine directly; instead, it is used behind the scenes by the ORM.

    In case of ORM, the configurational process starts by describing the database tables and then by defining classes which will be mapped to those tables. In SQLAlchemy, these two tasks are performed together. This is done by using Declarative system; the classes created include directives to describe the actual database table they are mapped to.

    A base class stores a catlog of classes and mapped tables in the Declarative system. This is called as the declarative base class. There will be usually just one instance of this base in a commonly imported module. The declarative_base() function is used to create base class. This function is defined in sqlalchemy.ext.declarative module.

    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    

    Once base classis declared, any number of mapped classes can be defined in terms of it. Following code defines a Customer’s class. It contains the table to be mapped to, and names and datatypes of columns in it.

    class Customers(Base):
       __tablename__ = ''customers''
    
       id = Column(Integer, primary_key = True)
       name = Column(String)
       address = Column(String)
       email = Column(String)
    

    A class in Declarative must have a __tablename__ attribute, and at least one Column which is part of a primary key. Declarative replaces all the Column objects with special Python accessors known as descriptors. This process is known as instrumentation which provides the means to refer to the table in a SQL context and enables persisting and loading the values of columns from the database.

    This mapped class like a normal Python class has attributes and methods as per the requirement.

    The information about class in Declarative system, is called as table metadata. SQLAlchemy uses Table object to represent this information for a specific table created by Declarative. The Table object is created according to the specifications, and is associated with the class by constructing a Mapper object. This mapper object is not directly used but is used internally as interface between mapped class and table.

    Each Table object is a member of larger collection known as MetaData and this object is available using the .metadata attribute of declarative base class. The MetaData.create_all() method is, passing in our Engine as a source of database connectivity. For all tables that haven’t been created yet, it issues CREATE TABLE statements to the database.

    Base.metadata.create_all(engine)
    

    The complete script to create a database and a table, and to map Python class is given below −

    from sqlalchemy import Column, Integer, String
    from sqlalchemy import create_engine
    engine = create_engine(''sqlite:///sales.db'', echo = True)
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    
    class Customers(Base):
       __tablename__ = ''customers''
       id = Column(Integer, primary_key=True)
    
       name = Column(String)
       address = Column(String)
       email = Column(String)
    Base.metadata.create_all(engine)
    

    When executed, Python console will echo following SQL expression being executed −

    CREATE TABLE customers (
       id INTEGER NOT NULL,
       name VARCHAR,
       address VARCHAR,
       email VARCHAR,
       PRIMARY KEY (id)
    )
    

    If we open the Sales.db using SQLiteStudio graphic tool, it shows customers table inside it with above mentioned structure.

    Customers Table

    SQLAlchemy ORM – Creating Session

    In order to interact with the database, we need to obtain its handle. A session object is the handle to database. Session class is defined using sessionmaker() – a configurable session factory method which is bound to the engine object created earlier.

    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind = engine)
    

    The session object is then set up using its default constructor as follows −

    session = Session()
    

    Some of the frequently required methods of session class are listed below −

    Sr.No. Method & Description
    1

    begin()

    begins a transaction on this session

    2

    add()

    places an object in the session. Its state is persisted in the database on next flush operation

    3

    add_all()

    adds a collection of objects to the session

    4

    commit()

    flushes all items and any transaction in progress

    5

    delete()

    marks a transaction as deleted

    6

    execute()

    executes a SQL expression

    7

    expire()

    marks attributes of an instance as out of date

    8

    flush()

    flushes all object changes to the database

    9

    invalidate()

    closes the session using connection invalidation

    10

    rollback()

    rolls back the current transaction in progress

    11

    close()

    Closes current session by clearing all items and ending any transaction in progress

    SQLAlchemy ORM – Adding Objects

    In the previous chapters of SQLAlchemy ORM, we have learnt how to declare mapping and create sessions. In this chapter, we will learn how to add objects to the table.

    We have declared Customer class that has been mapped to customers table. We have to declare an object of this class and persistently add it to the table by add() method of session object.

    c1 = Sales(name = ''Ravi Kumar'', address = ''Station Road Nanded'', email = ''ravi@gmail.com'')
    session.add(c1)
    

    Note that this transaction is pending until the same is flushed using commit() method.

    session.commit()
    

    Following is the complete script to add a record in customers table −

    from sqlalchemy import Column, Integer, String
    from sqlalchemy import create_engine
    engine = create_engine(''sqlite:///sales.db'', echo = True)
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    
    class Customers(Base):
       __tablename__ = ''customers''
    
       id = Column(Integer, primary_key=True)
       name = Column(String)
       address = Column(String)
       email = Column(String)
    
    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind = engine)
    session = Session()
    
    c1 = Customers(name = ''Ravi Kumar'', address = ''Station Road Nanded'', email = ''ravi@gmail.com'')
    
    session.add(c1)
    session.commit()
    

    To add multiple records, we can use add_all() method of the session class.

    session.add_all([
       Customers(name = ''Komal Pande'', address = ''Koti, Hyderabad'', email = ''komal@gmail.com''),
       Customers(name = ''Rajender Nath'', address = ''Sector 40, Gurgaon'', email = ''nath@gmail.com''),
       Customers(name = ''S.M.Krishna'', address = ''Budhwar Peth, Pune'', email = ''smk@gmail.com'')]
    )
    
    session.commit()
    

    Table view of SQLiteStudio shows that the records are persistently added in customers table. The following image shows the result −

    Customers Table Records Added

    SQLAlchemy ORM – Using Query

    All SELECT statements generated by SQLAlchemy ORM are constructed by Query object. It provides a generative interface, hence successive calls return a new Query object, a copy of the former with additional criteria and options associated with it.

    Query objects are initially generated using the query() method of the Session as follows −

    q = session.query(mapped class)
    

    Following statement is also equivalent to the above given statement −

    q = Query(mappedClass, session)
    

    The query object has all() method which returns a resultset in the form of list of objects. If we execute it on our customers table −

    result = session.query(Customers).all()
    

    This statement is effectively equivalent to following SQL expression −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    

    The result object can be traversed using For loop as below to obtain all records in underlying customers table. Here is the complete code to display all records in Customers table −

    from sqlalchemy import Column, Integer, String
    from sqlalchemy import create_engine
    engine = create_engine(''sqlite:///sales.db'', echo = True)
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    
    class Customers(Base):
       __tablename__ = ''customers''
       id = Column(Integer, primary_key =  True)
       name = Column(String)
    
       address = Column(String)
       email = Column(String)
    
    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind = engine)
    session = Session()
    result = session.query(Customers).all()
    
    for row in result:
       print ("Name: ",row.name, "Address:",row.address, "Email:",row.email)
    

    Python console shows list of records as below −

    Name: Ravi Kumar Address: Station Road Nanded Email: ravi@gmail.com
    Name: Komal Pande Address: Koti, Hyderabad Email: komal@gmail.com
    Name: Rajender Nath Address: Sector 40, Gurgaon Email: nath@gmail.com
    Name: S.M.Krishna Address: Budhwar Peth, Pune Email: smk@gmail.com
    

    The Query object also has following useful methods −

    Sr.No. Method & Description
    1

    add_columns()

    It adds one or more column expressions to the list of result columns to be returned.

    2

    add_entity()

    It adds a mapped entity to the list of result columns to be returned.

    3

    count()

    It returns a count of rows this Query would return.

    4

    delete()

    It performs a bulk delete query. Deletes rows matched by this query from the database.

    5

    distinct()

    It applies a DISTINCT clause to the query and return the newly resulting Query.

    6

    filter()

    It applies the given filtering criterion to a copy of this Query, using SQL expressions.

    7

    first()

    It returns the first result of this Query or None if the result doesn’t contain any row.

    8

    get()

    It returns an instance based on the given primary key identifier providing direct access to the identity map of the owning Session.

    9

    group_by()

    It applies one or more GROUP BY criterion to the query and return the newly resulting Query

    10

    join()

    It creates a SQL JOIN against this Query object’s criterion and apply generatively, returning the newly resulting Query.

    11

    one()

    It returns exactly one result or raise an exception.

    12

    order_by()

    It applies one or more ORDER BY criterion to the query and returns the newly resulting Query.

    13

    update()

    It performs a bulk update query and updates rows matched by this query in the database.

    SQLAlchemy ORM – Updating Objects

    In this chapter, we will see how to modify or update the table with desired values.

    To modify data of a certain attribute of any object, we have to assign new value to it and commit the changes to make the change persistent.

    Let us fetch an object from the table whose primary key identifier, in our Customers table with ID=2. We can use get() method of session as follows −

    x = session.query(Customers).get(2)
    

    We can display contents of the selected object with the below given code −

    print ("Name: ", x.name, "Address:", x.address, "Email:", x.email)
    

    From our customers table, following output should be displayed −

    Name: Komal Pande Address: Koti, Hyderabad Email: komal@gmail.com
    

    Now we need to update the Address field by assigning new value as given below −

    x.address = ''Banjara Hills Secunderabad''
    session.commit()
    

    The change will be persistently reflected in the database. Now we fetch object corresponding to first row in the table by using first() method as follows −

    x = session.query(Customers).first()
    

    This will execute following SQL expression −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    LIMIT ? OFFSET ?
    

    The bound parameters will be LIMIT = 1 and OFFSET = 0 respectively which means first row will be selected.

    print ("Name: ", x.name, "Address:", x.address, "Email:", x.email)
    

    Now, the output for the above code displaying the first row is as follows −

    Name: Ravi Kumar Address: Station Road Nanded Email: ravi@gmail.com
    

    Now change name attribute and display the contents using the below code −

    x.name = ''Ravi Shrivastava''
    print ("Name: ", x.name, "Address:", x.address, "Email:", x.email)
    

    The output of the above code is −

    Name: Ravi Shrivastava Address: Station Road Nanded Email: ravi@gmail.com
    

    Even though the change is displayed, it is not committed. You can retain the earlier persistent position by using rollback() method with the code below.

    session.rollback()
    
    print ("Name: ", x.name, "Address:", x.address, "Email:", x.email)
    

    Original contents of first record will be displayed.

    For bulk updates, we shall use update() method of the Query object. Let us try and give a prefix, ‘Mr.’ to name in each row (except ID = 2). The corresponding update() statement is as follows −

    session.query(Customers).filter(Customers.id! = 2).
    update({Customers.name:"Mr."+Customers.name}, synchronize_session = False)
    

    The update() method requires two parameters as follows −

    • A dictionary of key-values with key being the attribute to be updated, and value being the new contents of attribute.

    • synchronize_session attribute mentioning the strategy to update attributes in the session. Valid values are false: for not synchronizing the session, fetch: performs a select query before the update to find objects that are matched by the update query; and evaluate: evaluate criteria on objects in the session.

    Three out of 4 rows in the table will have name prefixed with ‘Mr.’ However, the changes are not committed and hence will not be reflected in the table view of SQLiteStudio. It will be refreshed only when we commit the session.

    SQLAlchemy ORM – Applying Filter

    In this chapter, we will discuss how to apply filter and also certain filter operations along with their codes.

    Resultset represented by Query object can be subjected to certain criteria by using filter() method. The general usage of filter method is as follows −

    session.query(class).filter(criteria)
    

    In the following example, resultset obtained by SELECT query on Customers table is filtered by a condition, (ID>2) −

    result = session.query(Customers).filter(Customers.id>2)
    

    This statement will translate into following SQL expression −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE customers.id > ?
    

    Since the bound parameter (?) is given as 2, only those rows with ID column>2 will be displayed. The complete code is given below −

    from sqlalchemy import Column, Integer, String
    from sqlalchemy import create_engine
    engine = create_engine(''sqlite:///sales.db'', echo = True)
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    
    class Customers(Base):
       __tablename__ = ''customers''
    
       id = Column(Integer, primary_key = True)
       name = Column(String)
    
       address = Column(String)
       email = Column(String)
    
    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind = engine)
    session = Session()
    result = session.query(Customers).filter(Customers.id>2)
    
    for row in result:
       print ("ID:", row.id, "Name: ",row.name, "Address:",row.address, "Email:",row.email)
    

    The output displayed in the Python console is as follows −

    ID: 3 Name: Rajender Nath Address: Sector 40, Gurgaon Email: nath@gmail.com
    ID: 4 Name: S.M.Krishna Address: Budhwar Peth, Pune Email: smk@gmail.com
    

    SQLAlchemy ORM – Filter Operators

    Now, we will learn the filter operations with their respective codes and output.

    Equals

    The usual operator used is == and it applies the criteria to check equality.

    result = session.query(Customers).filter(Customers.id == 2)
    
    for row in result:
       print ("ID:", row.id, "Name: ",row.name, "Address:",row.address, "Email:",row.email)
    

    SQLAlchemy will send following SQL expression −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE customers.id = ?
    

    The output for the above code is as follows −

    ID: 2 Name: Komal Pande Address: Banjara Hills Secunderabad Email: komal@gmail.com
    

    Not Equals

    The operator used for not equals is != and it provides not equals criteria.

    result = session.query(Customers).filter(Customers.id! = 2)
    
    for row in result:
       print ("ID:", row.id, "Name: ",row.name, "Address:",row.address, "Email:",row.email)
    

    The resulting SQL expression is −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE customers.id != ?
    

    The output for the above lines of code is as follows −

    ID: 1 Name: Ravi Kumar Address: Station Road Nanded Email: ravi@gmail.com
    ID: 3 Name: Rajender Nath Address: Sector 40, Gurgaon Email: nath@gmail.com
    ID: 4 Name: S.M.Krishna Address: Budhwar Peth, Pune Email: smk@gmail.com
    

    Like

    like() method itself produces the LIKE criteria for WHERE clause in the SELECT expression.

    result = session.query(Customers).filter(Customers.name.like(''Ra%''))
    for row in result:
       print ("ID:", row.id, "Name: ",row.name, "Address:",row.address, "Email:",row.email)
    

    Above SQLAlchemy code is equivalent to following SQL expression −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE customers.name LIKE ?
    

    And the output for the above code is −

    ID: 1 Name: Ravi Kumar Address: Station Road Nanded Email: ravi@gmail.com
    ID: 3 Name: Rajender Nath Address: Sector 40, Gurgaon Email: nath@gmail.com
    

    IN

    This operator checks whether the column value belongs to a collection of items in a list. It is provided by in_() method.

    result = session.query(Customers).filter(Customers.id.in_([1,3]))
    for row in result:
       print ("ID:", row.id, "Name: ",row.name, "Address:",row.address, "Email:",row.email)
    

    Here, the SQL expression evaluated by SQLite engine will be as follows −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE customers.id IN (?, ?)
    

    The output for the above code is as follows −

    ID: 1 Name: Ravi Kumar Address: Station Road Nanded Email: ravi@gmail.com
    ID: 3 Name: Rajender Nath Address: Sector 40, Gurgaon Email: nath@gmail.com
    

    AND

    This conjunction is generated by either putting multiple commas separated criteria in the filter or using and_() method as given below −

    result = session.query(Customers).filter(Customers.id>2, Customers.name.like(''Ra%''))
    for row in result:
       print ("ID:", row.id, "Name: ",row.name, "Address:",row.address, "Email:",row.email)
    

    from sqlalchemy import and_
    result = session.query(Customers).filter(and_(Customers.id>2, Customers.name.like(''Ra%'')))
    
    for row in result:
       print ("ID:", row.id, "Name: ",row.name, "Address:",row.address, "Email:",row.email)
    

    Both the above approaches result in similar SQL expression −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE customers.id > ? AND customers.name LIKE ?
    

    The output for the above lines of code is −

    ID: 3 Name: Rajender Nath Address: Sector 40, Gurgaon Email: nath@gmail.com
    

    OR

    This conjunction is implemented by or_() method.

    from sqlalchemy import or_
    result = session.query(Customers).filter(or_(Customers.id>2, Customers.name.like(''Ra%'')))
    
    for row in result:
       print ("ID:", row.id, "Name: ",row.name, "Address:",row.address, "Email:",row.email)
    

    As a result, SQLite engine gets following equivalent SQL expression −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE customers.id > ? OR customers.name LIKE ?
    

    The output for the above code is as follows −

    ID: 1 Name: Ravi Kumar Address: Station Road Nanded Email: ravi@gmail.com
    ID: 3 Name: Rajender Nath Address: Sector 40, Gurgaon Email: nath@gmail.com
    ID: 4 Name: S.M.Krishna Address: Budhwar Peth, Pune Email: smk@gmail.com
    

    Returning List and Scalars

    There are a number of methods of Query object that immediately issue SQL and return a value containing loaded database results.

    Here’s a brief rundown of returning list and scalars −

    all()

    It returns a list. Given below is the line of code for all() function.

    session.query(Customers).all()
    

    Python console displays following SQL expression emitted −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    

    first()

    It applies a limit of one and returns the first result as a scalar.

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    LIMIT ? OFFSET ?
    

    The bound parameters for LIMIT is 1 and for OFFSET is 0.

    one()

    This command fully fetches all rows, and if there is not exactly one object identity or composite row present in the result, it raises an error.

    session.query(Customers).one()
    

    With multiple rows found −

    MultipleResultsFound: Multiple rows were found for one()
    

    With no rows found −

    NoResultFound: No row was found for one()
    

    The one() method is useful for systems that expect to handle “no items found” versus “multiple items found” differently.

    scalar()

    It invokes the one() method, and upon success returns the first column of the row as follows −

    session.query(Customers).filter(Customers.id == 3).scalar()
    

    This generates following SQL statement −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE customers.id = ?
    

    SQLAlchemy ORM – Textual SQL

    Earlier, textual SQL using text() function has been explained from the perspective of core expression language of SQLAlchemy. Now we shall discuss it from ORM point of view.

    Literal strings can be used flexibly with Query object by specifying their use with the text() construct. Most applicable methods accept it. For example, filter() and order_by().

    In the example given below, the filter() method translates the string “id<3” to the WHERE id<3

    from sqlalchemy import text
    for cust in session.query(Customers).filter(text("id<3")):
       print(cust.name)
    

    The raw SQL expression generated shows conversion of filter to WHERE clause with the code illustrated below −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE id<3
    

    From our sample data in Customers table, two rows will be selected and name column will be printed as follows −

    Ravi Kumar
    Komal Pande
    

    To specify bind parameters with string-based SQL, use a colon,and to specify the values, use the params() method.

    cust = session.query(Customers).filter(text("id = :value")).params(value = 1).one()
    

    The effective SQL displayed on Python console will be as given below −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE id = ?
    

    To use an entirely string-based statement, a text() construct representing a complete statement can be passed to from_statement().

    session.query(Customers).from_statement(text("SELECT * FROM customers")).all()
    

    The result of above code will be a basic SELECT statement as given below −

    SELECT * FROM customers
    

    Obviously, all records in customers table will be selected.

    The text() construct allows us to link its textual SQL to Core or ORM-mapped column expressions positionally. We can achieve this by passing column expressions as positional arguments to the TextClause.columns() method.

    stmt = text("SELECT name, id, name, address, email FROM customers")
    stmt = stmt.columns(Customers.id, Customers.name)
    session.query(Customers.id, Customers.name).from_statement(stmt).all()
    

    The id and name columns of all rows will be selected even though the SQLite engine executes following expression generated by above code shows all columns in text() method −

    SELECT name, id, name, address, email FROM customers
    

    SQLAlchemy ORM – Building Relationship

    This session describes creation of another table which is related to already existing one in our database. The customers table contains master data of customers. We now need to create invoices table which may have any number of invoices belonging to a customer. This is a case of one to many relationships.

    Using declarative, we define this table along with its mapped class, Invoices as given below −

    from sqlalchemy import create_engine, ForeignKey, Column, Integer, String
    engine = create_engine(''sqlite:///sales.db'', echo = True)
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    from sqlalchemy.orm import relationship
    
    class Customer(Base):
       __tablename__ = ''customers''
    
       id = Column(Integer, primary_key = True)
       name = Column(String)
       address = Column(String)
       email = Column(String)
    
    class Invoice(Base):
       __tablename__ = ''invoices''
    
       id = Column(Integer, primary_key = True)
       custid = Column(Integer, ForeignKey(''customers.id''))
       invno = Column(Integer)
       amount = Column(Integer)
       customer = relationship("Customer", back_populates = "invoices")
    
    Customer.invoices = relationship("Invoice", order_by = Invoice.id, back_populates = "customer")
    Base.metadata.create_all(engine)
    

    This will send a CREATE TABLE query to SQLite engine as below −

    CREATE TABLE invoices (
       id INTEGER NOT NULL,
       custid INTEGER,
       invno INTEGER,
       amount INTEGER,
       PRIMARY KEY (id),
       FOREIGN KEY(custid) REFERENCES customers (id)
    )
    

    We can check that new table is created in sales.db with the help of SQLiteStudio tool.

    Sales.db New Table

    Invoices class applies ForeignKey construct on custid attribute. This directive indicates that values in this column should be constrained to be values present in id column in customers table. This is a core feature of relational databases, and is the “glue” that transforms unconnected collection of tables to have rich overlapping relationships.

    A second directive, known as relationship(), tells the ORM that the Invoice class should be linked to the Customer class using the attribute Invoice.customer. The relationship() uses the foreign key relationships between the two tables to determine the nature of this linkage, determining that it is many to one.

    An additional relationship() directive is placed on the Customer mapped class under the attribute Customer.invoices. The parameter relationship.back_populates is assigned to refer to the complementary attribute names, so that each relationship() can make intelligent decision about the same relationship as expressed in reverse. On one side, Invoices.customer refers to Invoices instance, and on the other side, Customer.invoices refers to a list of Customers instances.

    The relationship function is a part of Relationship API of SQLAlchemy ORM package. It provides a relationship between two mapped classes. This corresponds to a parent-child or associative table relationship.

    Following are the basic Relationship Patterns found −

    One To Many

    A One to Many relationship refers to parent with the help of a foreign key on the child table. relationship() is then specified on the parent, as referencing a collection of items represented by the child. The relationship.back_populates parameter is used to establish a bidirectional relationship in one-to-many, where the “reverse” side is a many to one.

    Many To One

    On the other hand, Many to One relationship places a foreign key in the parent table to refer to the child. relationship() is declared on the parent, where a new scalar-holding attribute will be created. Here again the relationship.back_populates parameter is used for Bidirectionalbehaviour.

    One To One

    One To One relationship is essentially a bidirectional relationship in nature. The uselist flag indicates the placement of a scalar attribute instead of a collection on the “many” side of the relationship. To convert one-to-many into one-to-one type of relation, set uselist parameter to false.

    Many To Many

    Many to Many relationship is established by adding an association table related to two classes by defining attributes with their foreign keys. It is indicated by the secondary argument to relationship(). Usually, the Table uses the MetaData object associated with the declarative base class, so that the ForeignKey directives can locate the remote tables with which to link. The relationship.back_populates parameter for each relationship() establishes a bidirectional relationship. Both sides of the relationship contain a collection.

    Working with Related Objects

    In this chapter, we will focus on the related objects in SQLAlchemy ORM.

    Now when we create a Customer object, a blank invoice collection will be present in the form of Python List.

    c1 = Customer(name = "Gopal Krishna", address = "Bank Street Hydarebad", email = "gk@gmail.com")
    

    The invoices attribute of c1.invoices will be an empty list. We can assign items in the list as −

    c1.invoices = [Invoice(invno = 10, amount = 15000), Invoice(invno = 14, amount = 3850)]
    

    Let us commit this object to the database using Session object as follows −

    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind = engine)
    session = Session()
    session.add(c1)
    session.commit()
    

    This will automatically generate INSERT queries for customers and invoices tables −

    INSERT INTO customers (name, address, email) VALUES (?, ?, ?)
    (''Gopal Krishna'', ''Bank Street Hydarebad'', ''gk@gmail.com'')
    INSERT INTO invoices (custid, invno, amount) VALUES (?, ?, ?)
    (2, 10, 15000)
    INSERT INTO invoices (custid, invno, amount) VALUES (?, ?, ?)
    (2, 14, 3850)
    

    Let us now look at contents of customers table and invoices table in the table view of SQLiteStudio −

    Customers Table View

    Invoices Table

    You can construct Customer object by providing mapped attribute of invoices in the constructor itself by using the below command −

    c2 = [
       Customer(
          name = "Govind Pant",
          address = "Gulmandi Aurangabad",
          email = "gpant@gmail.com",
          invoices = [Invoice(invno = 3, amount = 10000),
          Invoice(invno = 4, amount = 5000)]
       )
    ]
    

    Or a list of objects to be added using add_all() function of session object as shown below −

    rows = [
       Customer(
          name = "Govind Kala",
          address = "Gulmandi Aurangabad",
          email = "kala@gmail.com",
          invoices = [Invoice(invno = 7, amount = 12000), Invoice(invno = 8, amount = 18500)]),
    
       Customer(
          name = "Abdul Rahman",
          address = "Rohtak",
          email = "abdulr@gmail.com",
          invoices = [Invoice(invno = 9, amount = 15000),
          Invoice(invno = 11, amount = 6000)
       ])
    ]
    
    session.add_all(rows)
    session.commit()
    

    SQLAlchemy ORM – Working with Joins

    Now that we have two tables, we will see how to create queries on both tables at the same time. To construct a simple implicit join between Customer and Invoice, we can use Query.filter() to equate their related columns together. Below, we load the Customer and Invoice entities at once using this method −

    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind = engine)
    session = Session()
    
    for c, i in session.query(Customer, Invoice).filter(Customer.id == Invoice.custid).all():
       print ("ID: {} Name: {} Invoice No: {} Amount: {}".format(c.id,c.name, i.invno, i.amount))
    

    The SQL expression emitted by SQLAlchemy is as follows −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email, invoices.id
    AS invoices_id, invoices.custid
    AS invoices_custid, invoices.invno
    AS invoices_invno, invoices.amount
    AS invoices_amount
    FROM customers, invoices
    WHERE customers.id = invoices.custid
    

    And the result of the above lines of code is as follows −

    ID: 2 Name: Gopal Krishna Invoice No: 10 Amount: 15000
    ID: 2 Name: Gopal Krishna Invoice No: 14 Amount: 3850
    ID: 3 Name: Govind Pant Invoice No: 3 Amount: 10000
    ID: 3 Name: Govind Pant Invoice No: 4 Amount: 5000
    ID: 4 Name: Govind Kala Invoice No: 7 Amount: 12000
    ID: 4 Name: Govind Kala Invoice No: 8 Amount: 8500
    ID: 5 Name: Abdul Rahman Invoice No: 9 Amount: 15000
    ID: 5 Name: Abdul Rahman Invoice No: 11 Amount: 6000
    

    The actual SQL JOIN syntax is easily achieved using the Query.join() method as follows −

    session.query(Customer).join(Invoice).filter(Invoice.amount == 8500).all()
    

    The SQL expression for join will be displayed on the console −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers JOIN invoices ON customers.id = invoices.custid
    WHERE invoices.amount = ?
    

    We can iterate through the result using for loop −

    result = session.query(Customer).join(Invoice).filter(Invoice.amount == 8500)
    for row in result:
       for inv in row.invoices:
          print (row.id, row.name, inv.invno, inv.amount)
    

    With 8500 as the bind parameter, following output is displayed −

    4 Govind Kala 8 8500
    

    Query.join() knows how to join between these tables because there’s only one foreign key between them. If there were no foreign keys, or more foreign keys, Query.join() works better when one of the following forms are used −

    query.join(Invoice, id == Address.custid) explicit condition
    query.join(Customer.invoices) specify relationship from left to right
    query.join(Invoice, Customer.invoices) same, with explicit target
    query.join(”invoices”) same, using a string

    Similarly outerjoin() function is available to achieve left outer join.

    query.outerjoin(Customer.invoices)
    

    The subquery() method produces a SQL expression representing SELECT statement embedded within an alias.

    from sqlalchemy.sql import func
    
    stmt = session.query(
       Invoice.custid, func.count(''*'').label(''invoice_count'')
    ).group_by(Invoice.custid).subquery()
    

    The stmt object will contain a SQL statement as below −

    SELECT invoices.custid, count(:count_1) AS invoice_count FROM invoices GROUP BY invoices.custid
    

    Once we have our statement, it behaves like a Table construct. The columns on the statement are accessible through an attribute called c as shown in the below code −

    for u, count in session.query(Customer, stmt.c.invoice_count).outerjoin(stmt, Customer.id == stmt.c.custid).order_by(Customer.id):
       print(u.name, count)
    

    The above for loop displays name-wise count of invoices as follows −

    Arjun Pandit None
    Gopal Krishna 2
    Govind Pant 2
    Govind Kala 2
    Abdul Rahman 2
    

    Common Relationship Operators

    In this chapter, we will discuss about the operators which build on relationships.

    __eq__()

    The above operator is a many-to-one “equals” comparison. The line of code for this operator is as shown below −

    s = session.query(Customer).filter(Invoice.invno.__eq__(12))
    

    The equivalent SQL query for the above line of code is −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers, invoices
    WHERE invoices.invno = ?
    

    __ne__()

    This operator is a many-to-one “not equals” comparison. The line of code for this operator is as shown below −

    s = session.query(Customer).filter(Invoice.custid.__ne__(2))
    

    The equivalent SQL query for the above line of code is given below −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers, invoices
    WHERE invoices.custid != ?
    

    contains()

    This operator is used for one-to-many collections and given below is the code for contains() −

    s = session.query(Invoice).filter(Invoice.invno.contains([3,4,5]))
    

    The equivalent SQL query for the above line of code is −

    SELECT invoices.id
    AS invoices_id, invoices.custid
    AS invoices_custid, invoices.invno
    AS invoices_invno, invoices.amount
    AS invoices_amount
    FROM invoices
    WHERE (invoices.invno LIKE ''%'' + ? || ''%'')
    

    any()

    any() operator is used for collections as shown below −

    s = session.query(Customer).filter(Customer.invoices.any(Invoice.invno==11))
    

    The equivalent SQL query for the above line of code is shown below −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE EXISTS (
       SELECT 1
       FROM invoices
       WHERE customers.id = invoices.custid
       AND invoices.invno = ?)
    

    has()

    This operator is used for scalar references as follows −

    s = session.query(Invoice).filter(Invoice.customer.has(name = ''Arjun Pandit''))
    

    The equivalent SQL query for the above line of code is −

    SELECT invoices.id
    AS invoices_id, invoices.custid
    AS invoices_custid, invoices.invno
    AS invoices_invno, invoices.amount
    AS invoices_amount
    FROM invoices
    WHERE EXISTS (
       SELECT 1
       FROM customers
       WHERE customers.id = invoices.custid
       AND customers.name = ?)
    

    SQLAlchemy ORM – Eager Loading

    Eager load reduces the number of queries. SQLAlchemy offers eager loading functions invoked via query options which give additional instructions to the Query. These options determine how to load various attributes via the Query.options() method.

    Subquery Load

    We want that Customer.invoices should load eagerly. The orm.subqueryload() option gives a second SELECT statement that fully loads the collections associated with the results just loaded. The name “subquery” causes the SELECT statement to be constructed directly via the Query re-used and embedded as a subquery into a SELECT against the related table.

    from sqlalchemy.orm import subqueryload
    c1 = session.query(Customer).options(subqueryload(Customer.invoices)).filter_by(name = ''Govind Pant'').one()
    

    This results in the following two SQL expressions −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE customers.name = ?
    (''Govind Pant'',)
    
    SELECT invoices.id
    AS invoices_id, invoices.custid
    AS invoices_custid, invoices.invno
    AS invoices_invno, invoices.amount
    AS invoices_amount, anon_1.customers_id
    AS anon_1_customers_id
    FROM (
       SELECT customers.id
       AS customers_id
       FROM customers
       WHERE customers.name = ?)
    
    AS anon_1
    JOIN invoices
    ON anon_1.customers_id = invoices.custid
    ORDER BY anon_1.customers_id, invoices.id 2018-06-25 18:24:47,479
    INFO sqlalchemy.engine.base.Engine (''Govind Pant'',)
    

    To access the data from two tables, we can use the below program −

    print (c1.name, c1.address, c1.email)
    
    for x in c1.invoices:
       print ("Invoice no : {}, Amount : {}".format(x.invno, x.amount))
    

    The output of the above program is as follows −

    Govind Pant Gulmandi Aurangabad gpant@gmail.com
    Invoice no : 3, Amount : 10000
    Invoice no : 4, Amount : 5000
    

    Joined Load

    The other function is called orm.joinedload(). This emits a LEFT OUTER JOIN. Lead object as well as the related object or collection is loaded in one step.

    from sqlalchemy.orm import joinedload
    c1 = session.query(Customer).options(joinedload(Customer.invoices)).filter_by(name=''Govind Pant'').one()
    

    This emits following expression giving same output as above −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email, invoices_1.id
    AS invoices_1_id, invoices_1.custid
    AS invoices_1_custid, invoices_1.invno
    AS invoices_1_invno, invoices_1.amount
    AS invoices_1_amount
    
    FROM customers
    LEFT OUTER JOIN invoices
    AS invoices_1
    ON customers.id = invoices_1.custid
    
    WHERE customers.name = ? ORDER BY invoices_1.id
    (''Govind Pant'',)
    

    The OUTER JOIN resulted in two rows, but it gives one instance of Customer back. This is because Query applies a “uniquing” strategy, based on object identity, to the returned entities. Joined eager loading can be applied without affecting the query results.

    The subqueryload() is more appropriate for loading related collections while joinedload() is better suited for many-to-one relationship.

    SQLAlchemy ORM – Deleting Related Objects

    It is easy to perform delete operation on a single table. All you have to do is to delete an object of the mapped class from a session and commit the action. However, delete operation on multiple related tables is little tricky.

    In our sales.db database, Customer and Invoice classes are mapped to customer and invoice table with one to many type of relationship. We will try to delete Customer object and see the result.

    As a quick reference, below are the definitions of Customer and Invoice classes −

    from sqlalchemy import create_engine, ForeignKey, Column, Integer, String
    engine = create_engine(''sqlite:///sales.db'', echo = True)
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    from sqlalchemy.orm import relationship
    class Customer(Base):
       __tablename__ = ''customers''
    
       id = Column(Integer, primary_key = True)
       name = Column(String)
       address = Column(String)
       email = Column(String)
    
    class Invoice(Base):
       __tablename__ = ''invoices''
    
       id = Column(Integer, primary_key = True)
       custid = Column(Integer, ForeignKey(''customers.id''))
       invno = Column(Integer)
       amount = Column(Integer)
       customer = relationship("Customer", back_populates = "invoices")
    
    Customer.invoices = relationship("Invoice", order_by = Invoice.id, back_populates = "customer")
    

    We setup a session and obtain a Customer object by querying it with primary ID using the below program −

    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind=engine)
    session = Session()
    x = session.query(Customer).get(2)
    

    In our sample table, x.name happens to be ”Gopal Krishna”. Let us delete this x from the session and count the occurrence of this name.

    session.delete(x)
    session.query(Customer).filter_by(name = ''Gopal Krishna'').count()
    

    The resulting SQL expression will return 0.

    SELECT count(*)
    AS count_1
    FROM (
       SELECT customers.id
       AS customers_id, customers.name
       AS customers_name, customers.address
       AS customers_address, customers.email
       AS customers_email
       FROM customers
       WHERE customers.name = ?)
    AS anon_1(''Gopal Krishna'',) 0
    

    However, the related Invoice objects of x are still there. It can be verified by the following code −

    session.query(Invoice).filter(Invoice.invno.in_([10,14])).count()
    

    Here, 10 and 14 are invoice numbers belonging to customer Gopal Krishna. Result of the above query is 2, which means the related objects have not been deleted.

    SELECT count(*)
    AS count_1
    FROM (
       SELECT invoices.id
       AS invoices_id, invoices.custid
       AS invoices_custid, invoices.invno
       AS invoices_invno, invoices.amount
       AS invoices_amount
       FROM invoices
       WHERE invoices.invno IN (?, ?))
    AS anon_1(10, 14) 2
    

    This is because SQLAlchemy doesn’t assume the deletion of cascade; we have to give a command to delete it.

    To change the behavior, we configure cascade options on the User.addresses relationship. Let us close the ongoing session, use new declarative_base() and redeclare the User class, adding in the addresses relationship including the cascade configuration.

    The cascade attribute in relationship function is a comma-separated list of cascade rules which determines how Session operations should be “cascaded” from parent to child. By default, it is False, which means that it is “save-update, merge”.

    The available cascades are as follows −

    • save-update
    • merge
    • expunge
    • delete
    • delete-orphan
    • refresh-expire

    Often used option is “all, delete-orphan” to indicate that related objects should follow along with the parent object in all cases, and be deleted when de-associated.

    Hence redeclared Customer class is shown below −

    class Customer(Base):
       __tablename__ = ''customers''
    
       id = Column(Integer, primary_key = True)
       name = Column(String)
       address = Column(String)
       email = Column(String)
       invoices = relationship(
          "Invoice",
          order_by = Invoice.id,
          back_populates = "customer",
          cascade = "all,
          delete, delete-orphan"
       )
    

    Let us delete the Customer with Gopal Krishna name using the below program and see the count of its related Invoice objects −

    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind = engine)
    session = Session()
    x = session.query(Customer).get(2)
    session.delete(x)
    session.query(Customer).filter_by(name = ''Gopal Krishna'').count()
    session.query(Invoice).filter(Invoice.invno.in_([10,14])).count()
    

    The count is now 0 with following SQL emitted by above script −

    SELECT customers.id
    AS customers_id, customers.name
    AS customers_name, customers.address
    AS customers_address, customers.email
    AS customers_email
    FROM customers
    WHERE customers.id = ?
    (2,)
    SELECT invoices.id
    AS invoices_id, invoices.custid
    AS invoices_custid, invoices.invno
    AS invoices_invno, invoices.amount
    AS invoices_amount
    FROM invoices
    WHERE ? = invoices.custid
    ORDER BY invoices.id (2,)
    DELETE FROM invoices
    WHERE invoices.id = ? ((1,), (2,))
    DELETE FROM customers
    WHERE customers.id = ? (2,)
    SELECT count(*)
    AS count_1
    FROM (
       SELECT customers.id
       AS customers_id, customers.name
       AS customers_name, customers.address
       AS customers_address, customers.email
       AS customers_email
       FROM customers
       WHERE customers.name = ?)
    AS anon_1(''Gopal Krishna'',)
    SELECT count(*)
    AS count_1
    FROM (
       SELECT invoices.id
       AS invoices_id, invoices.custid
       AS invoices_custid, invoices.invno
       AS invoices_invno, invoices.amount
       AS invoices_amount
       FROM invoices
       WHERE invoices.invno IN (?, ?))
    AS anon_1(10, 14)
    0
    

    Many to Many Relationships

    Many to Many relationship between two tables is achieved by adding an association table such that it has two foreign keys – one from each table’s primary key. Moreover, classes mapping to the two tables have an attribute with a collection of objects of other association tables assigned as secondary attribute of relationship() function.

    For this purpose, we shall create a SQLite database (mycollege.db) with two tables – department and employee. Here, we assume that an employee is a part of more than one department, and a department has more than one employee. This constitutes many-to-many relationship.

    Definition of Employee and Department classes mapped to department and employee table is as follows −

    from sqlalchemy import create_engine, ForeignKey, Column, Integer, String
    engine = create_engine(''sqlite:///mycollege.db'', echo = True)
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    from sqlalchemy.orm import relationship
    
    class Department(Base):
       __tablename__ = ''department''
       id = Column(Integer, primary_key = True)
       name = Column(String)
       employees = relationship(''Employee'', secondary = ''link'')
    
    class Employee(Base):
       __tablename__ = ''employee''
       id = Column(Integer, primary_key = True)
       name = Column(String)
       departments = relationship(Department,secondary=''link'')
    

    We now define a Link class. It is linked to link table and contains department_id and employee_id attributes respectively referencing to primary keys of department and employee table.

    class Link(Base):
       __tablename__ = ''link''
       department_id = Column(
          Integer,
          ForeignKey(''department.id''),
          primary_key = True)
    
    employee_id = Column(
       Integer,
       ForeignKey(''employee.id''),
       primary_key = True)
    

    Here, we have to make a note that Department class has employees attribute related to Employee class. The relationship function’s secondary attribute is assigned a link as its value.

    Similarly, Employee class has departments attribute related to Department class. The relationship function’s secondary attribute is assigned a link as its value.

    All these three tables are created when the following statement is executed −

    Base.metadata.create_all(engine)
    

    The Python console emits following CREATE TABLE queries −

    CREATE TABLE department (
       id INTEGER NOT NULL,
       name VARCHAR,
       PRIMARY KEY (id)
    )
    
    CREATE TABLE employee (
       id INTEGER NOT NULL,
       name VARCHAR,
       PRIMARY KEY (id)
    )
    
    CREATE TABLE link (
       department_id INTEGER NOT NULL,
       employee_id INTEGER NOT NULL,
       PRIMARY KEY (department_id, employee_id),
       FOREIGN KEY(department_id) REFERENCES department (id),
       FOREIGN KEY(employee_id) REFERENCES employee (id)
    )
    

    We can check this by opening mycollege.db using SQLiteStudio as shown in the screenshots given below −

    Department Table

    Employee Table

    Link Table

    Next we create three objects of Department class and three objects of Employee class as shown below −

    d1 = Department(name = "Accounts")
    d2 = Department(name = "Sales")
    d3 = Department(name = "Marketing")
    
    e1 = Employee(name = "John")
    e2 = Employee(name = "Tony")
    e3 = Employee(name = "Graham")
    

    Each table has a collection attribute having append() method. We can add Employee objects to Employees collection of Department object. Similarly, we can add Department objects to departments collection attribute of Employee objects.

    e1.departments.append(d1)
    e2.departments.append(d3)
    d1.employees.append(e3)
    d2.employees.append(e2)
    d3.employees.append(e1)
    e3.departments.append(d2)
    

    All we have to do now is to set up a session object, add all objects to it and commit the changes as shown below −

    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind = engine)
    session = Session()
    session.add(e1)
    session.add(e2)
    session.add(d1)
    session.add(d2)
    session.add(d3)
    session.add(e3)
    session.commit()
    

    Following SQL statements will be emitted on Python console −

    INSERT INTO department (name) VALUES (?) (''Accounts'',)
    INSERT INTO department (name) VALUES (?) (''Sales'',)
    INSERT INTO department (name) VALUES (?) (''Marketing'',)
    INSERT INTO employee (name) VALUES (?) (''John'',)
    INSERT INTO employee (name) VALUES (?) (''Graham'',)
    INSERT INTO employee (name) VALUES (?) (''Tony'',)
    INSERT INTO link (department_id, employee_id) VALUES (?, ?) ((1, 2), (3, 1), (2, 3))
    INSERT INTO link (department_id, employee_id) VALUES (?, ?) ((1, 1), (2, 2), (3, 3))
    

    To check the effect of above operations, use SQLiteStudio and view data in department, employee and link tables −

    Department Table Data

    Employee Table Data

    Link Table Data

    To display the data, run the following query statement −

    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind = engine)
    session = Session()
    
    for x in session.query( Department, Employee).filter(Link.department_id == Department.id,
       Link.employee_id == Employee.id).order_by(Link.department_id).all():
       print ("Department: {} Name: {}".format(x.Department.name, x.Employee.name))
    

    As per the data populated in our example, output will be displayed as below −

    Department: Accounts Name: John
    Department: Accounts Name: Graham
    Department: Sales Name: Graham
    Department: Sales Name: Tony
    Department: Marketing Name: John
    Department: Marketing Name: Tony
    

    SQLAlchemy – Dialects

    SQLAlchemy uses system of dialects to communicate with various types of databases. Each database has a corresponding DBAPI wrapper. All dialects require that an appropriate DBAPI driver is installed.

    Following dialects are included in SQLAlchemy API −

    • Firebird
    • Microsoft SQL Server
    • MySQL
    • Oracle
    • PostgreSQL
    • SQL
    • Sybase

    An Engine object based on a URL is produced by create_engine() function. These URLs can include username, password, hostname, and database name. There may be optional keyword arguments for additional configuration. In some cases, a file path is accepted, and in others, a “data source name” replaces the “host” and “database” portions. The typical form of a database URL is as follows −

    dialect+driver://username:password@host:port/database
    

    PostgreSQL

    The PostgreSQL dialect uses psycopg2 as the default DBAPI. pg8000 is also available as a pure-Python substitute as shown below:

    # default
    engine = create_engine(''postgresql://scott:tiger@localhost/mydatabase'')
    
    # psycopg2
    engine = create_engine(''postgresql+psycopg2://scott:tiger@localhost/mydatabase'')
    
    # pg8000
    engine = create_engine(''postgresql+pg8000://scott:tiger@localhost/mydatabase'')
    

    MySQL

    The MySQL dialect uses mysql-python as the default DBAPI. There are many MySQL DBAPIs available, such as MySQL-connector-python as follows −

    # default
    engine = create_engine(''mysql://scott:tiger@localhost/foo'')
    
    # mysql-python
    engine = create_engine(''mysql+mysqldb://scott:tiger@localhost/foo'')
    
    # MySQL-connector-python
    engine = create_engine(''mysql+mysqlconnector://scott:tiger@localhost/foo'')
    

    Oracle

    The Oracle dialect uses cx_oracle as the default DBAPI as follows −

    engine = create_engine(''oracle://scott:tiger@127.0.0.1:1521/sidname'')
    engine = create_engine(''oracle+cx_oracle://scott:tiger@tnsname'')
    

    Microsoft SQL Server

    The SQL Server dialect uses pyodbc as the default DBAPI. pymssql is also available.

    # pyodbc
    engine = create_engine(''mssql+pyodbc://scott:tiger@mydsn'')
    
    # pymssql
    engine = create_engine(''mssql+pymssql://scott:tiger@hostname:port/dbname'')
    

    SQLite

    SQLite connects to file-based databases, using the Python built-in module sqlite3 by default. As SQLite connects to local files, the URL format is slightly different. The “file” portion of the URL is the filename of the database. For a relative file path, this requires three slashes as shown below −

    engine = create_engine(''sqlite:///foo.db'')
    

    And for an absolute file path, the three slashes are followed by the absolute path as given below −

    engine = create_engine(''sqlite:///C:\path\to\foo.db'')
    

    To use a SQLite:memory:database, specify an empty URL as given below −

    engine = create_engine(''sqlite://'')
    

    Conclusion

    In the first part of this tutorial, we have learnt how to use the Expression Language to execute SQL statements. Expression language embeds SQL constructs in Python code. In the second part, we have discussed object relation mapping capability of SQLAlchemy. The ORM API maps the SQL tables with Python classes.


    Khóa học lập trình tại Toidayhoc vừa học vừa làm dự án vừa nhận lương: Khóa học lập trình nhận lương tại trung tâm Toidayhoc

  • Khóa học miễn phí Many to Many Relationships nhận dự án làm có lương

    Many to Many Relationships



    Many to Many relationship between two tables is achieved by adding an association table such that it has two foreign keys – one from each table’s primary key. Moreover, classes mapping to the two tables have an attribute with a collection of objects of other association tables assigned as secondary attribute of relationship() function.

    For this purpose, we shall create a SQLite database (mycollege.db) with two tables – department and employee. Here, we assume that an employee is a part of more than one department, and a department has more than one employee. This constitutes many-to-many relationship.

    Definition of Employee and Department classes mapped to department and employee table is as follows −

    from sqlalchemy import create_engine, ForeignKey, Column, Integer, String
    engine = create_engine(''sqlite:///mycollege.db'', echo = True)
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    from sqlalchemy.orm import relationship
    
    class Department(Base):
       __tablename__ = ''department''
       id = Column(Integer, primary_key = True)
       name = Column(String)
       employees = relationship(''Employee'', secondary = ''link'')
    
    class Employee(Base):
       __tablename__ = ''employee''
       id = Column(Integer, primary_key = True)
       name = Column(String)
       departments = relationship(Department,secondary=''link'')
    

    We now define a Link class. It is linked to link table and contains department_id and employee_id attributes respectively referencing to primary keys of department and employee table.

    class Link(Base):
       __tablename__ = ''link''
       department_id = Column(
          Integer,
          ForeignKey(''department.id''),
          primary_key = True)
    
    employee_id = Column(
       Integer,
       ForeignKey(''employee.id''),
       primary_key = True)
    

    Here, we have to make a note that Department class has employees attribute related to Employee class. The relationship function’s secondary attribute is assigned a link as its value.

    Similarly, Employee class has departments attribute related to Department class. The relationship function’s secondary attribute is assigned a link as its value.

    All these three tables are created when the following statement is executed −

    Base.metadata.create_all(engine)
    

    The Python console emits following CREATE TABLE queries −

    CREATE TABLE department (
       id INTEGER NOT NULL,
       name VARCHAR,
       PRIMARY KEY (id)
    )
    
    CREATE TABLE employee (
       id INTEGER NOT NULL,
       name VARCHAR,
       PRIMARY KEY (id)
    )
    
    CREATE TABLE link (
       department_id INTEGER NOT NULL,
       employee_id INTEGER NOT NULL,
       PRIMARY KEY (department_id, employee_id),
       FOREIGN KEY(department_id) REFERENCES department (id),
       FOREIGN KEY(employee_id) REFERENCES employee (id)
    )
    

    We can check this by opening mycollege.db using SQLiteStudio as shown in the screenshots given below −

    Department Table

    Employee Table

    Link Table

    Next we create three objects of Department class and three objects of Employee class as shown below −

    d1 = Department(name = "Accounts")
    d2 = Department(name = "Sales")
    d3 = Department(name = "Marketing")
    
    e1 = Employee(name = "John")
    e2 = Employee(name = "Tony")
    e3 = Employee(name = "Graham")
    

    Each table has a collection attribute having append() method. We can add Employee objects to Employees collection of Department object. Similarly, we can add Department objects to departments collection attribute of Employee objects.

    e1.departments.append(d1)
    e2.departments.append(d3)
    d1.employees.append(e3)
    d2.employees.append(e2)
    d3.employees.append(e1)
    e3.departments.append(d2)
    

    All we have to do now is to set up a session object, add all objects to it and commit the changes as shown below −

    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind = engine)
    session = Session()
    session.add(e1)
    session.add(e2)
    session.add(d1)
    session.add(d2)
    session.add(d3)
    session.add(e3)
    session.commit()
    

    Following SQL statements will be emitted on Python console −

    INSERT INTO department (name) VALUES (?) (''Accounts'',)
    INSERT INTO department (name) VALUES (?) (''Sales'',)
    INSERT INTO department (name) VALUES (?) (''Marketing'',)
    INSERT INTO employee (name) VALUES (?) (''John'',)
    INSERT INTO employee (name) VALUES (?) (''Graham'',)
    INSERT INTO employee (name) VALUES (?) (''Tony'',)
    INSERT INTO link (department_id, employee_id) VALUES (?, ?) ((1, 2), (3, 1), (2, 3))
    INSERT INTO link (department_id, employee_id) VALUES (?, ?) ((1, 1), (2, 2), (3, 3))
    

    To check the effect of above operations, use SQLiteStudio and view data in department, employee and link tables −

    Department Table Data

    Employee Table Data

    Link Table Data

    To display the data, run the following query statement −

    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind = engine)
    session = Session()
    
    for x in session.query( Department, Employee).filter(Link.department_id == Department.id,
       Link.employee_id == Employee.id).order_by(Link.department_id).all():
       print ("Department: {} Name: {}".format(x.Department.name, x.Employee.name))
    

    As per the data populated in our example, output will be displayed as below −

    Department: Accounts Name: John
    Department: Accounts Name: Graham
    Department: Sales Name: Graham
    Department: Sales Name: Tony
    Department: Marketing Name: John
    Department: Marketing Name: Tony
    

    Khóa học lập trình tại Toidayhoc vừa học vừa làm dự án vừa nhận lương: Khóa học lập trình nhận lương tại trung tâm Toidayhoc

  • Khóa học miễn phí Dialects nhận dự án làm có lương

    SQLAlchemy – Dialects



    SQLAlchemy uses system of dialects to communicate with various types of databases. Each database has a corresponding DBAPI wrapper. All dialects require that an appropriate DBAPI driver is installed.

    Following dialects are included in SQLAlchemy API −

    • Firebird
    • Microsoft SQL Server
    • MySQL
    • Oracle
    • PostgreSQL
    • SQL
    • Sybase

    An Engine object based on a URL is produced by create_engine() function. These URLs can include username, password, hostname, and database name. There may be optional keyword arguments for additional configuration. In some cases, a file path is accepted, and in others, a “data source name” replaces the “host” and “database” portions. The typical form of a database URL is as follows −

    dialect+driver://username:password@host:port/database
    

    PostgreSQL

    The PostgreSQL dialect uses psycopg2 as the default DBAPI. pg8000 is also available as a pure-Python substitute as shown below:

    # default
    engine = create_engine(''postgresql://scott:tiger@localhost/mydatabase'')
    
    # psycopg2
    engine = create_engine(''postgresql+psycopg2://scott:tiger@localhost/mydatabase'')
    
    # pg8000
    engine = create_engine(''postgresql+pg8000://scott:tiger@localhost/mydatabase'')
    

    MySQL

    The MySQL dialect uses mysql-python as the default DBAPI. There are many MySQL DBAPIs available, such as MySQL-connector-python as follows −

    # default
    engine = create_engine(''mysql://scott:tiger@localhost/foo'')
    
    # mysql-python
    engine = create_engine(''mysql+mysqldb://scott:tiger@localhost/foo'')
    
    # MySQL-connector-python
    engine = create_engine(''mysql+mysqlconnector://scott:tiger@localhost/foo'')
    

    Oracle

    The Oracle dialect uses cx_oracle as the default DBAPI as follows −

    engine = create_engine(''oracle://scott:tiger@127.0.0.1:1521/sidname'')
    engine = create_engine(''oracle+cx_oracle://scott:tiger@tnsname'')
    

    Microsoft SQL Server

    The SQL Server dialect uses pyodbc as the default DBAPI. pymssql is also available.

    # pyodbc
    engine = create_engine(''mssql+pyodbc://scott:tiger@mydsn'')
    
    # pymssql
    engine = create_engine(''mssql+pymssql://scott:tiger@hostname:port/dbname'')
    

    SQLite

    SQLite connects to file-based databases, using the Python built-in module sqlite3 by default. As SQLite connects to local files, the URL format is slightly different. The “file” portion of the URL is the filename of the database. For a relative file path, this requires three slashes as shown below −

    engine = create_engine(''sqlite:///foo.db'')
    

    And for an absolute file path, the three slashes are followed by the absolute path as given below −

    engine = create_engine(''sqlite:///C:\path\to\foo.db'')
    

    To use a SQLite:memory:database, specify an empty URL as given below −

    engine = create_engine(''sqlite://'')
    

    Conclusion

    In the first part of this tutorial, we have learnt how to use the Expression Language to execute SQL statements. Expression language embeds SQL constructs in Python code. In the second part, we have discussed object relation mapping capability of SQLAlchemy. The ORM API maps the SQL tables with Python classes.


    Khóa học lập trình tại Toidayhoc vừa học vừa làm dự án vừa nhận lương: Khóa học lập trình nhận lương tại trung tâm Toidayhoc