Run a SQL query script against an Access database
execsql.py

execsql.py is a Python module and program that allows you to apply a SQL query script stored in a text file to an Access database. The output of the last SQL query in the script can be automatically saved in a CSV file or routed to—and then viewed in—an Excel worksheet.

Capabilities

You can use the execsql program to:

Syntax and Options

execsql.py <sqlfile> <Access_db> [output_spec] Arguments: <sqlfile> The name of a text file of SQL commands to be executed. Required argument. <Access_db> The name of the Access database against which to run the SQL. Required argument. [output_spec] The name of a CSV file to which the output of the last SQL command should be written, or the literal string "Excel" to send output to a Microsoft Excel workbook in memory.

Notes

Requirements

The execsql program used the Common Object Model (COM) to communicate with Access and Excel. Python does not include a standard library that supports COM, and so execsql uses Mark Hammond's pywin32 extension for Windows to provide COM support. A version of pywin32 compatible with your version of Python must be installed so that execsql can be used.

Support for CREATE TEMPORARY QUERY DDL

The syntax of the "CREATE TEMPORARY QUERY" DDL supported by execsql is:

CREATE [TEMP[ORARY]] QUERY|VIEW <query_name> AS <sql_command>

The "TEMPORARY" specification is optional: if it is included, the query will be deleted after the entire script has been executed, and if it is not, the query will remain defined in the database after the script completes. If a query of the same name is already defined in the Access database when the script runs, the existing query will be deleted before the new one is created—no check is performed to determine whether the new and old queries have the same definition, and no warning is issued by execsql that a query definition has been replaced.

The keyword "VIEW" can be used in place of the keyword "QUERY". This alternative provides compatibility with the "CREATE TEMPORARY VIEW" command in PostgreSQL, and minimizes the need to edit any scripts that are intended to be run against both Access and PostgreSQL databases.

Using Script Files

Using script files to store and execute task-specific queries has a number of advantages over using separate individual queries within the Access database itself:

A Few Comments on SQL used with Jet and DAO

The version of SQL that is used by the Jet engine and Microsoft's Data Access Objects (DAO) methods, and thus that must be used in the script files executed with execsql, is generally equivalent to that used within Access itself, but is not identical, and is also not the same in all respects as standard SQL; it also differs in some respects from the SQL that can be used with Access via ODBC (which is more standards-compliant). A few points to bear in mind when creating SQL scripts for use with Access:

Example

This example illustrates a script that makes use of several temporary queries to select and summarize data, and a final query that prepares the data for export or further use. This example is intended to be run against an EQuIS database.

-- -------------------------------------------------------------------- -- Get result records that meet specific selection criteria. -- -------------------------------------------------------------------- create temporary view v_seldata as select smp.sys_sample_code, rs.test_surrogate_key, rs.cas_rn, tst.lab_anl_method_name, iif(rs.detect_flag='N', rs.method_detection_limit, rs.result_value) as conc, rs.detect_flag='Y' as detected, rs.lab_qualifiers like '*J*' as estimated, iif(rs.detect_flag='N', rs.detection_limit_unit, rs.result_unit) as unit from ((((dt_result as rs inner join dt_test as tst on tst.test_surrogate_key=rs.test_surrogate_key) inner join dt_sample as smp on smp.sys_sample_code=tst.sys_sample_code) inner join dt_field_sample as fs on fs.sys_sample_code=smp.sys_sample_code) inner join dt_location as loc on loc.sys_loc_code=fs.sys_loc_code) inner join rt_analyte as anal on anal.cas_rn=rs.cas_rn where (loc.loc_name like 'SG*' or loc.loc_name like 'SC*') and smp.sample_type_code='N' and smp.sample_matrix_code='SE' and anal.analyte_type in ('ABN', 'PEST', 'PCB', 'LPAH', 'HPAH') and rs.reportable_result='Yes' and not (rs.result_value is null and rs.method_detection_limit is null); -- -------------------------------------------------------------------- -- Summarize by sample, taking nondetects at half the detection limit. -- -------------------------------------------------------------------- create temporary view v_samp as select sys_sample_code, cas_rn, lab_anl_method_name, Avg(iif(detected, conc, conc/2.0)) as concentration, Max(iif(detected is null, 0, detected)) as detect, Min(iif(estimated is null, 0, estimated)) as estimate, unit from v_seldata group by sys_sample_code, cas_rn, lab_anl_method_name, unit; -- -------------------------------------------------------------------- -- Pull in sample location and date information, decode analyte, -- and reconstruct qualifiers. -- -------------------------------------------------------------------- select loc.loc_name, fs.sample_date, fs.start_depth, fs.end_depth, fs.depth_unit, smp.sample_name, anal.chemical_name, dat.lab_anl_method_name, iif(dat.detect, concentration, concentration/2.0) as conc, (iif(detect, "", "U") & iif(estimate, "J", "")) as qualifiers, unit from (((v_samp as dat inner join dt_sample as smp on dat.sys_sample_code=smp.sys_sample_code) inner join dt_field_sample as fs on fs.sys_sample_code=smp.sys_sample_code) inner join dt_location as loc on loc.sys_loc_code=fs.sys_loc_code) inner join rt_analyte as anal on anal.cas_rn=dat.cas_rn;

During the execution of this script, the temporary queries will be created in the database. When the script concludes, the temporary queries will be removed. Nothing except the data itself need be kept in the database to use a script like this one.

Copyright and License

Copyright (c) 2008, R.Dreas Nielsen

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. The GNU General Public License is available at http://www.gnu.org/licenses/.