├── code ├── section_i │ └── build.gradle.kts ├── section_ii │ ├── 2_1_simple_select.R │ ├── 2_1_simple_select.java │ ├── 2_1_simple_select.py │ ├── 2_2_single_select.R │ ├── 2_2_single_select.py │ ├── 2_3_mapping_to_class.java │ ├── 2_3_mapping_to_class.py │ ├── 2_4_select_function.R │ ├── 2_4_select_function.py │ ├── 2_5_reading_dataframe.java │ ├── 2_5_reading_dataframe.py │ ├── 2_6_fluent_constructs.R │ ├── 2_6_fluent_constructs.java │ ├── 2_6_fluent_constructs.py │ └── thunderbird_manufacturing.db ├── section_iii │ ├── 3_1_passing_parameters.R │ ├── 3_1_passing_parameters.java │ ├── 3_1_passing_parameters.py │ ├── 3_2_passing_multiple_parameters.R │ ├── 3_2_passing_multiple_parameters.java │ ├── 3_2_passing_multiple_parameters.py │ ├── 3_3_insert_single_record.R │ ├── 3_3_insert_single_record.java │ ├── 3_3_insert_single_record.py │ ├── 3_4_retrieving_key_for_insert.java │ ├── 3_4_retrieving_key_for_insert.py │ ├── 3_5_update_and_delete.R │ ├── 3_5_update_and_delete.java │ ├── 3_5_update_and_delete.py │ ├── 3_6_successful_transaction.R │ ├── 3_6_successful_transaction.java │ ├── 3_6_successful_transaction.py │ ├── 3_7_failed_transaction.R │ ├── 3_7_failed_transaction.java │ ├── 3_7_failed_transaction.py │ ├── 3_8_batch_insert.R │ ├── 3_8_batch_insert.java │ ├── 3_8_batch_insert.py │ ├── 3_9_dataframe_insert.py │ └── thunderbird_manufacturing.db └── section_iv │ ├── 4_1_pooling.R │ ├── 4_1_pooling.java │ ├── 4_1_pooling.py │ ├── 4_2_pooling_and_concurrency.java │ ├── 4_2_pooling_and_concurrency.py │ ├── 4_3_pooling_transaction.R │ ├── 4_4_connection_releasing.R │ ├── 4_4_connection_releasing.java │ ├── 4_4_connection_releasing.py │ ├── 4_5_try_with_resources.java │ └── thunderbird_manufacturing.db ├── oreilly_programming_with_sql.pdf ├── oreilly_programming_with_sql.pptx └── thunderbird_manufacturing.db /code/section_i/build.gradle.kts: -------------------------------------------------------------------------------- 1 | 2 | repositories { 3 | mavenCentral() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | implementation("com.zaxxer:HikariCP:3.4.1") 9 | implementation("org.xerial:sqlite-jdbc:3.30.1") 10 | implementation("tech.tablesaw:tablesaw-core:0.36.0") 11 | } 12 | -------------------------------------------------------------------------------- /code/section_ii/2_1_simple_select.R: -------------------------------------------------------------------------------- 1 | library(DBI) 2 | library(RSQLite) 3 | 4 | db <- dbConnect(SQLite(), dbname='thunderbird_manufacturing.db') 5 | 6 | my_query <- dbSendQuery(db, "SELECT * FROM CUSTOMER") 7 | my_data <- dbFetch(my_query, n = -1) 8 | 9 | dbClearResult(my_query) 10 | print(my_data) 11 | 12 | remove(my_query) 13 | dbDisconnect(db) -------------------------------------------------------------------------------- /code/section_ii/2_1_simple_select.java: -------------------------------------------------------------------------------- 1 | import java.sql.Connection; 2 | import java.sql.DriverManager; 3 | import java.sql.ResultSet; 4 | import java.sql.Statement; 5 | 6 | public class JavaLauncher { 7 | 8 | public static void main(String[] args) { 9 | 10 | try { 11 | // Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 12 | Connection conn = DriverManager.getConnection("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 13 | 14 | Statement stmt = conn.createStatement(); 15 | ResultSet rs = stmt.executeQuery("SELECT * FROM CUSTOMER"); 16 | 17 | while (rs.next()) { 18 | System.out.println(rs.getInt("CUSTOMER_ID") + " " + rs.getString("CUSTOMER_NAME")); 19 | } 20 | //release connection 21 | conn.close(); 22 | 23 | } catch (Exception e) { 24 | e.printStackTrace(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /code/section_ii/2_1_simple_select.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 4 | conn = engine.connect() 5 | 6 | stmt = text("SELECT * FROM CUSTOMER") 7 | results = conn.execute(stmt) 8 | 9 | for record in results: 10 | print(record) 11 | 12 | # by field name 13 | # for record in results: 14 | # print("{0} - {1}".format(record["CUSTOMER_ID"], record["CUSTOMER_NAME"])) -------------------------------------------------------------------------------- /code/section_ii/2_2_single_select.R: -------------------------------------------------------------------------------- 1 | library(DBI) 2 | library(RSQLite) 3 | 4 | db <- dbConnect(SQLite(), dbname='thunderbird_manufacturing.db') 5 | 6 | my_query <- dbSendQuery(db, "SELECT * FROM CUSTOMER LIMIT 1") 7 | my_data <- dbFetch(my_query, n = 1) 8 | 9 | dbClearResult(my_query) 10 | 11 | remove(my_query) 12 | dbDisconnect(db) 13 | print(my_data) -------------------------------------------------------------------------------- /code/section_ii/2_2_single_select.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 4 | conn = engine.connect() 5 | 6 | stmt = text("SELECT * FROM CUSTOMER LIMIT 1") 7 | single_result = conn.execute(stmt).fetchone() 8 | 9 | print(single_result) -------------------------------------------------------------------------------- /code/section_ii/2_3_mapping_to_class.java: -------------------------------------------------------------------------------- 1 | import java.sql.Connection; 2 | import java.sql.DriverManager; 3 | import java.sql.ResultSet; 4 | import java.sql.Statement; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class JavaLauncher { 9 | 10 | public static void main(String[] args) { 11 | 12 | try { 13 | //Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 14 | Connection conn = DriverManager.getConnection("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 15 | 16 | Statement stmt = conn.createStatement(); 17 | ResultSet rs = stmt.executeQuery("SELECT * from CUSTOMER"); 18 | 19 | List customers = new ArrayList<>(); 20 | 21 | while (rs.next()) { 22 | customers.add( 23 | new Customer(rs.getInt("CUSTOMER_ID"), 24 | rs.getString("CUSTOMER_NAME"), 25 | rs.getString("ADDRESS"), 26 | rs.getString("CITY"), 27 | rs.getString("STATE"), 28 | rs.getInt("ZIP"), 29 | rs.getString("CATEGORY") 30 | ) 31 | ); 32 | } 33 | 34 | System.out.println(customers); 35 | 36 | //release connection 37 | conn.close(); 38 | 39 | } catch (Exception e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | 44 | public static class Customer { 45 | 46 | private final int customerId; 47 | private final String customerName; 48 | private final String address; 49 | private final String city; 50 | private final String state; 51 | private final int zip; 52 | private final String category; 53 | 54 | public Customer(int customerId, String customerName, String address, String city, String state, int zip, String category) { 55 | this.customerId = customerId; 56 | this.customerName = customerName; 57 | this.address = address; 58 | this.city = city; 59 | this.state = state; 60 | this.zip = zip; 61 | this.category = category; 62 | } 63 | 64 | public int getCustomerId() { 65 | return customerId; 66 | } 67 | 68 | public String getCustomerName() { 69 | return customerName; 70 | } 71 | 72 | public String getAddress() { 73 | return address; 74 | } 75 | 76 | public String getCity() { 77 | return city; 78 | } 79 | 80 | public String getState() { 81 | return state; 82 | } 83 | 84 | public int getZip() { 85 | return zip; 86 | } 87 | 88 | public String getCategory() { 89 | return category; 90 | } 91 | 92 | @Override 93 | public String toString() { 94 | return "Customer{" + 95 | "customerId=" + customerId + 96 | ", customerName='" + customerName + '\'' + 97 | ", address='" + address + '\'' + 98 | ", city='" + city + '\'' + 99 | ", state='" + state + '\'' + 100 | ", zip=" + zip + 101 | ", category='" + category + '\'' + 102 | '}'; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /code/section_ii/2_3_mapping_to_class.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 4 | conn = engine.connect() 5 | 6 | stmt = text("SELECT * FROM CUSTOMER") 7 | results = conn.execute(stmt) 8 | 9 | 10 | class Customer: 11 | def __init__(self, record): 12 | self.id = int(record["CUSTOMER_ID"]) 13 | self.name = record["CUSTOMER_NAME"] 14 | self.address = record["ADDRESS"] 15 | self.city = record["CITY"] 16 | self.state = record["STATE"] 17 | self.zip = int(record["ZIP"]) 18 | self.category = record["CATEGORY"] 19 | 20 | def __repr__(self): 21 | return "{0} - {1}".format(self.id, self.name) 22 | 23 | 24 | for record in results: 25 | print(Customer(record)) -------------------------------------------------------------------------------- /code/section_ii/2_4_select_function.R: -------------------------------------------------------------------------------- 1 | 2 | all_customers <- function { 3 | library(DBI) 4 | library(RSQLite) 5 | 6 | db <- dbConnect(SQLite(), dbname='thunderbird_manufacturing.db') 7 | 8 | my_query <- dbSendQuery(db, "SELECT * FROM CUSTOMER") 9 | my_data <- dbFetch(my_query, n = -1) 10 | 11 | dbClearResult(my_query) 12 | print(my_data) 13 | 14 | remove(my_query) 15 | dbDisconnect(db) 16 | return(my_data) 17 | } -------------------------------------------------------------------------------- /code/section_ii/2_4_select_function.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 4 | conn = engine.connect() 5 | 6 | def get_all_customers(): 7 | stmt = text("SELECT * FROM CUSTOMER") 8 | return list(conn.execute(stmt)) 9 | 10 | 11 | print(get_all_customers()) -------------------------------------------------------------------------------- /code/section_ii/2_5_reading_dataframe.java: -------------------------------------------------------------------------------- 1 | import tech.tablesaw.api.Table; 2 | 3 | import java.sql.Connection; 4 | import java.sql.DriverManager; 5 | import java.sql.ResultSet; 6 | import java.sql.Statement; 7 | 8 | public class JavaLauncher { 9 | 10 | // Documentation 11 | // https://jtablesaw.github.io/tablesaw/userguide/importing_data.html 12 | 13 | public static void main(String[] args) { 14 | 15 | try { 16 | 17 | //Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 18 | Connection conn = DriverManager.getConnection("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 19 | 20 | Statement stmt = conn.createStatement(); 21 | ResultSet rs = stmt.executeQuery("SELECT * FROM CUSTOMER"); 22 | 23 | Table customer = Table.read().db(rs); 24 | 25 | System.out.println(customer); 26 | 27 | conn.close(); 28 | } catch (Exception e) { 29 | throw new RuntimeException(e); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /code/section_ii/2_5_reading_dataframe.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | import pandas as pd 3 | 4 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 5 | conn = engine.connect() 6 | 7 | df = pd.read_sql("SELECT * FROM CUSTOMER", conn) 8 | print(df) 9 | 10 | 11 | # with options 12 | 13 | from sqlalchemy import create_engine, text 14 | import pandas as pd 15 | 16 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 17 | conn = engine.connect() 18 | 19 | df = pd.read_sql("SELECT CUSTOMER_ORDER_ID, ORDER_DATE FROM CUSTOMER_ORDER", 20 | conn, 21 | coerce_float=True, 22 | parse_dates=["ORDER_DATE"]) 23 | print(df) -------------------------------------------------------------------------------- /code/section_ii/2_6_fluent_constructs.R: -------------------------------------------------------------------------------- 1 | 2 | library(DBI) 3 | library(RSQLite) 4 | library(dplyr) 5 | 6 | db <- dbConnect(SQLite(), dbname='thunderbird_manufacturing.db') 7 | 8 | my_query <- dbSendQuery(db, "SELECT * FROM CUSTOMER") 9 | df <- dbFetch(my_query, n = -1) 10 | 11 | tx_only <- df %>% filter(df['STATE'] == 'TX') 12 | 13 | dbClearResult(my_query) 14 | print(tx_only) 15 | 16 | dbDisconnect(db) 17 | -------------------------------------------------------------------------------- /code/section_ii/2_6_fluent_constructs.java: -------------------------------------------------------------------------------- 1 | import java.sql.*; 2 | import java.util.*; 3 | import java.util.function.Consumer; 4 | import java.util.stream.Collectors; 5 | import java.util.stream.Stream; 6 | import java.util.stream.StreamSupport; 7 | 8 | public class JavaLauncher { 9 | 10 | public static void main(String[] args) { 11 | 12 | try { 13 | 14 | //Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 15 | Connection conn = DriverManager.getConnection("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 16 | 17 | Statement stmt = conn.createStatement(); 18 | ResultSet rs = stmt.executeQuery("SELECT * FROM CUSTOMER"); 19 | 20 | StreamHelper.asStream(rs) 21 | .filter(r -> r.get("CATEGORY", String.class).equals("COMMERCIAL")) 22 | .forEach(r -> System.out.println(r)); 23 | 24 | conn.close(); 25 | } catch (Exception e) { 26 | throw new RuntimeException(e); 27 | } 28 | } 29 | 30 | public static final class StreamHelper { 31 | 32 | // CREDIT: https://kozelljozsef.blogspot.com/2018/04/java-8-jdbc-resultset-to-stream.html 33 | 34 | public static class Record { 35 | private final Map fields = new HashMap<>(16); 36 | private final long count; 37 | 38 | private Record(final ResultSet resultSet) throws SQLException { 39 | final ResultSetMetaData metaData = resultSet.getMetaData(); 40 | count = metaData.getColumnCount(); 41 | for (int i = 1; i <= count; ++i) { 42 | fields.put(metaData.getColumnName(i), resultSet.getObject(i)); 43 | } 44 | } 45 | 46 | /** 47 | * Is there a column named like this? 48 | * 49 | * @param columnName is the column name in the query. 50 | * @return True if found. 51 | */ 52 | public boolean contains(final String columnName) { 53 | return fields.containsKey(columnName); 54 | } 55 | 56 | /** 57 | * Number of columns. 58 | * 59 | * @return Numer of columns. 60 | */ 61 | public long count() { 62 | return count; 63 | } 64 | 65 | /** 66 | * Get value casted to the requested type. 67 | *

68 | * No type checking happens inside. It is your job to know the datatype in the database. 69 | *

70 | * Example: 71 | 72 | * {@code record.get("COLUMN1", Long.class); // returns a Long} 73 | * 74 | * @param columnName is the column name in the query. 75 | * @param type is Java type of the column. 76 | * @return The value casted to the Java type. 77 | */ 78 | public T get(final String columnName, final Class type) { 79 | return type.cast(getObject(columnName)); 80 | } 81 | 82 | /** 83 | * Get columns in the record. 84 | * 85 | * @return Collection of the column names. 86 | */ 87 | public Set getColumns() { 88 | return Collections.unmodifiableSet(fields.keySet()); 89 | } 90 | 91 | /** 92 | * Get value as an object. 93 | * 94 | * @param columnName is the column name in the query. 95 | * @return The value. 96 | */ 97 | public Object getObject(final String columnName) { 98 | return fields.get(columnName); 99 | } 100 | 101 | /** 102 | * Get value as string. 103 | * 104 | * @param columnName is the column name in the query. 105 | * @return Value as string. 106 | */ 107 | public String getString(final String columnName) { 108 | return Objects.toString(fields.get(columnName)); 109 | } 110 | 111 | /** 112 | * Is the given cell null? 113 | * 114 | * @param columnName is the column name in the query. 115 | * @return True if null. 116 | */ 117 | public boolean isNull(final String columnName) { 118 | return getObject(columnName) == null; 119 | } 120 | 121 | @Override 122 | public String toString() { 123 | return fields.entrySet().stream().map(e -> e.getKey() + ": " + e.getValue()) 124 | .collect(Collectors.joining(", ")); 125 | } 126 | } 127 | 128 | /** 129 | * Wrap a ResultSet in a Stream. 130 | *

131 | * The wrapper consumes the result set. The caller must close the result set after the stream 132 | * processing was finished. 133 | * 134 | * @param resultSet is the open result set to streamline. 135 | * @return A stream of rows. 136 | */ 137 | public static Stream asStream(final ResultSet resultSet) { 138 | // "est = Long.MAX_VALUE if infinite, unknown, or too expensive to compute." 139 | return StreamSupport.stream(new Spliterators.AbstractSpliterator(Long.MAX_VALUE, 140 | Spliterator.NONNULL | Spliterator.IMMUTABLE) { 141 | @Override 142 | public boolean tryAdvance(final Consumer action) { 143 | try { 144 | if (!resultSet.next()) { 145 | return false; 146 | } 147 | } catch (@SuppressWarnings("unused") final SQLException e) { 148 | return false; 149 | } 150 | try { 151 | action.accept(new Record(resultSet)); 152 | } catch (@SuppressWarnings("unused") final SQLException e) { 153 | return false; 154 | } 155 | return true; 156 | } 157 | }, true).parallel(); 158 | } 159 | 160 | private StreamHelper() { /* Hidden. */ } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /code/section_ii/2_6_fluent_constructs.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 4 | conn = engine.connect() 5 | 6 | 7 | class Customer: 8 | def __init__(self, record): 9 | self.id = int(record["CUSTOMER_ID"]) 10 | self.name = record["CUSTOMER_NAME"] 11 | self.address = record["ADDRESS"] 12 | self.city = record["CITY"] 13 | self.state = record["STATE"] 14 | self.zip = int(record["ZIP"]) 15 | self.category = record["CATEGORY"] 16 | 17 | def __repr__(self): 18 | return "{0} - {1}".format(self.id, self.name) 19 | 20 | 21 | all_customers = [Customer(record) for record in conn.execute(text("SELECT * FROM CUSTOMER"))] 22 | 23 | print(all_customers) 24 | 25 | -------------------------------------------------------------------------------- /code/section_ii/thunderbird_manufacturing.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasnield/oreilly_programming_with_sql/ef673d38795ebd2bfac73b1fe92613ef0f3fbcab/code/section_ii/thunderbird_manufacturing.db -------------------------------------------------------------------------------- /code/section_iii/3_1_passing_parameters.R: -------------------------------------------------------------------------------- 1 | library(DBI) 2 | library(RSQLite) 3 | 4 | db <- dbConnect(SQLite(), dbname='thunderbird_manufacturing.db') 5 | 6 | sql <- "SELECT * FROM CUSTOMER WHERE CUSTOMER_ID = ?" 7 | 8 | my_query <- dbSendQuery(db, sql, params = list(3)) 9 | my_data <- dbFetch(my_query, n = 1) 10 | 11 | dbClearResult(my_query) 12 | remove(my_query) 13 | dbDisconnect(db) 14 | print(my_data) -------------------------------------------------------------------------------- /code/section_iii/3_1_passing_parameters.java: -------------------------------------------------------------------------------- 1 | import java.sql.Connection; 2 | import java.sql.DriverManager; 3 | import java.sql.PreparedStatement; 4 | import java.sql.ResultSet; 5 | 6 | public class JavaLauncher { 7 | 8 | public static void main(String[] args) { 9 | 10 | try { 11 | 12 | //Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 13 | Connection conn = DriverManager.getConnection("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 14 | PreparedStatement stmt = conn.prepareStatement("SELECT * FROM CUSTOMER WHERE CATEGORY = ?"); 15 | 16 | stmt.setString(1, "COMMERCIAL"); 17 | ResultSet rs = stmt.executeQuery(); 18 | 19 | while (rs.next()) { 20 | System.out.println(rs.getString("CUSTOMER_NAME") + " is categorized as " + rs.getString("CATEGORY")); 21 | } 22 | 23 | conn.close(); 24 | } catch (Exception e) { 25 | throw new RuntimeException(e); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /code/section_iii/3_1_passing_parameters.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 4 | conn = engine.connect() 5 | 6 | 7 | def customer_for_id(customer_id): 8 | stmt = text("SELECT * FROM CUSTOMER WHERE CUSTOMER_ID = :id") 9 | return conn.execute(stmt, id=customer_id).first() 10 | 11 | 12 | print(customer_for_id(3)) -------------------------------------------------------------------------------- /code/section_iii/3_2_passing_multiple_parameters.R: -------------------------------------------------------------------------------- 1 | library(DBI) 2 | library(RSQLite) 3 | 4 | db <- dbConnect(SQLite(), dbname='thunderbird_manufacturing.db') 5 | 6 | sql <- "SELECT * FROM CUSTOMER WHERE STATE = ? AND CATEGORY = ?" 7 | 8 | my_query <- dbSendQuery(db, sql, params = list('TX', 'COMMERCIAL')) 9 | my_data <- dbFetch(my_query, n = -1) 10 | 11 | dbClearResult(my_query) 12 | remove(my_query) 13 | dbDisconnect(db) 14 | print(my_data) -------------------------------------------------------------------------------- /code/section_iii/3_2_passing_multiple_parameters.java: -------------------------------------------------------------------------------- 1 | import java.sql.Connection; 2 | import java.sql.DriverManager; 3 | import java.sql.PreparedStatement; 4 | import java.sql.ResultSet; 5 | 6 | public class JavaLauncher { 7 | 8 | public static void main(String[] args) { 9 | 10 | try { 11 | 12 | //Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 13 | Connection conn = DriverManager.getConnection("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 14 | 15 | PreparedStatement stmt = conn.prepareStatement("SELECT * FROM CUSTOMER WHERE STATE = ? AND CATEGORY = ?"); 16 | 17 | stmt.setString(1, "TX"); 18 | stmt.setString(2, "COMMERCIAL"); 19 | 20 | ResultSet rs = stmt.executeQuery(); 21 | 22 | while (rs.next()) { 23 | System.out.println(rs.getInt("CUSTOMER_ID") + "," + rs.getString("CUSTOMER_NAME") + "," + rs.getString("STATE") + "," + rs.getString("CATEGORY")); 24 | } 25 | 26 | conn.close(); 27 | } catch (Exception e) { 28 | throw new RuntimeException(e); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /code/section_iii/3_2_passing_multiple_parameters.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 4 | conn = engine.connect() 5 | 6 | stmt = text("SELECT * FROM CUSTOMER WHERE STATE = :state AND CATEGORY = :category") 7 | results = conn.execute(stmt, state='TX', category='COMMERCIAL') 8 | 9 | for r in results: 10 | print(r) -------------------------------------------------------------------------------- /code/section_iii/3_3_insert_single_record.R: -------------------------------------------------------------------------------- 1 | 2 | library(DBI) 3 | library(RSQLite) 4 | 5 | db <- dbConnect(SQLite(), dbname='thunderbird_manufacturing.db') 6 | 7 | new_record = c("Brittania Solutions, LLC", "2374 Collie Way","Frisco","TX",75035,"COMMERCIAL") 8 | 9 | my_insert <- "INSERT INTO CUSTOMER (CUSTOMER_NAME, ADDRESS, CITY, STATE, ZIP, CATEGORY) VALUES (?,?,?,?,?,?)" 10 | dbExecute(db, my_insert, params= new_record) 11 | 12 | 13 | dbDisconnect(db) 14 | 15 | -------------------------------------------------------------------------------- /code/section_iii/3_3_insert_single_record.java: -------------------------------------------------------------------------------- 1 | import java.sql.Connection; 2 | import java.sql.DriverManager; 3 | import java.sql.PreparedStatement; 4 | import java.sql.ResultSet; 5 | 6 | public class JavaLauncher { 7 | 8 | public static void main(String[] args) { 9 | 10 | try { 11 | 12 | //Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 13 | Connection conn = DriverManager.getConnection("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 14 | PreparedStatement insertStmt = conn.prepareStatement("INSERT INTO CUSTOMER (CUSTOMER_NAME, ADDRESS, CITY, STATE, ZIP, CATEGORY) VALUES (?,?,?,?,?,?)"); 15 | 16 | insertStmt.setString(1, "Brittania Solutions, LLC"); 17 | insertStmt.setString(2, "2374 Collie Way"); 18 | insertStmt.setString(3, "Frisco"); 19 | insertStmt.setString(4, "TX"); 20 | insertStmt.setInt(5, 75035); 21 | insertStmt.setString(6, "COMMERCIAL"); 22 | 23 | // Execute INSERT 24 | insertStmt.execute(); 25 | 26 | // Select all records to check 27 | PreparedStatement selectStmt = conn.prepareStatement("SELECT * FROM CUSTOMER"); 28 | ResultSet rs = selectStmt.executeQuery(); 29 | 30 | while (rs.next()) { 31 | System.out.println(rs.getInt("CUSTOMER_ID") + "," + rs.getString("CUSTOMER_NAME") + "," + rs.getString("STATE") + "," + rs.getString("CATEGORY")); 32 | } 33 | 34 | conn.close(); 35 | } catch (Exception e) { 36 | throw new RuntimeException(e); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /code/section_iii/3_3_insert_single_record.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 4 | conn = engine.connect() 5 | 6 | # INSERT a new record 7 | stmt = text("INSERT INTO CUSTOMER (CUSTOMER_NAME, ADDRESS, CITY, STATE, ZIP, CATEGORY) VALUES (:customerName,:address,:city,:state,:zip,:category)") 8 | 9 | conn.execute(stmt, customerName = "Brittania Solutions, LLC", 10 | address="2374 Collie Way", 11 | city="Frisco", 12 | state="TX", 13 | zip= 75035, 14 | category="COMMERCIAL" 15 | ) 16 | 17 | # Check records to see if last one inserted 18 | for r in conn.execute(text("SELECT * FROM CUSTOMER")): 19 | print(r) 20 | 21 | conn.close() -------------------------------------------------------------------------------- /code/section_iii/3_4_retrieving_key_for_insert.java: -------------------------------------------------------------------------------- 1 | import java.sql.Connection; 2 | import java.sql.DriverManager; 3 | import java.sql.PreparedStatement; 4 | import java.sql.ResultSet; 5 | 6 | public class JavaLauncher { 7 | 8 | public static void main(String[] args) { 9 | 10 | try { 11 | 12 | //Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 13 | Connection conn = DriverManager.getConnection("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 14 | PreparedStatement insertStmt = conn.prepareStatement("INSERT INTO CUSTOMER (CUSTOMER_NAME, ADDRESS, CITY, STATE, ZIP, CATEGORY) VALUES (?,?,?,?,?,?)"); 15 | 16 | insertStmt.setString(1, "Brittania Solutions, LLC"); 17 | insertStmt.setString(2, "2374 Collie Way"); 18 | insertStmt.setString(3, "Frisco"); 19 | insertStmt.setString(4, "TX"); 20 | insertStmt.setInt(5, 75035); 21 | insertStmt.setString(6, "COMMERCIAL"); 22 | 23 | // Execute INSERT 24 | insertStmt.execute(); 25 | 26 | // Get the generated key for the new record 27 | int newRecordId = insertStmt.getGeneratedKeys().getInt(1); 28 | 29 | // Get the new record 30 | PreparedStatement selectStmt = conn.prepareStatement("SELECT * FROM CUSTOMER WHERE CUSTOMER_ID = ?"); 31 | selectStmt.setInt(1, newRecordId); 32 | ResultSet rs = selectStmt.executeQuery(); 33 | 34 | while (rs.next()) { 35 | System.out.println(rs.getInt("CUSTOMER_ID") + "," + rs.getString("CUSTOMER_NAME") + "," + rs.getString("STATE") + "," + rs.getString("CATEGORY")); 36 | } 37 | 38 | conn.close(); 39 | } catch (Exception e) { 40 | throw new RuntimeException(e); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /code/section_iii/3_4_retrieving_key_for_insert.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 4 | conn = engine.connect() 5 | 6 | insertStmt = text("INSERT INTO CUSTOMER (CUSTOMER_NAME, ADDRESS, CITY, STATE, ZIP, CATEGORY) VALUES (:customerName,:address,:city,:state,:zip,:category)") 7 | 8 | insertResults = conn.execute(insertStmt, customerName ="Brittania Solutions, LLC", 9 | address="2374 Collie Way", 10 | city="Frisco", 11 | state="TX", 12 | zip= 75035, 13 | category="COMMERCIAL" 14 | ) 15 | 16 | print("Last inserted record has CUSTOMER_ID {0}".format(insertResults.lastrowid)) 17 | 18 | conn.close() -------------------------------------------------------------------------------- /code/section_iii/3_5_update_and_delete.R: -------------------------------------------------------------------------------- 1 | 2 | library(DBI) 3 | library(RSQLite) 4 | library(dplyr) 5 | 6 | db <- dbConnect(SQLite(), dbname='thunderbird_manufacturing.db') 7 | 8 | 9 | # Perform delete of customer records with ID greater than 10 10 | my_delete <- "DELETE FROM CUSTOMER WHERE CUSTOMER_ID > ?" 11 | dbExecute(db, my_delete, params= 10) 12 | 13 | 14 | # Perform update of customer 15 | my_update <- "UPDATE CUSTOMER SET STATE = lower(STATE)" 16 | dbExecute(db, my_update) 17 | 18 | 19 | # Check Records 20 | my_query <- dbSendQuery(db, "SELECT * FROM CUSTOMER") 21 | my_data <- dbFetch(my_query, n = -1) 22 | 23 | # Cleanup 24 | dbClearResult(my_query) 25 | print(my_data) 26 | remove(my_query) 27 | dbDisconnect(db) 28 | 29 | -------------------------------------------------------------------------------- /code/section_iii/3_5_update_and_delete.java: -------------------------------------------------------------------------------- 1 | import java.sql.*; 2 | 3 | public class JavaLauncher { 4 | 5 | public static void main(String[] args) { 6 | 7 | try { 8 | 9 | //Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 10 | Connection conn = DriverManager.getConnection("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 11 | 12 | // Delete customers with ID greater than 10 13 | PreparedStatement ps = conn.prepareStatement("DELETE FROM CUSTOMER WHERE CUSTOMER_ID > ?"); 14 | ps.setInt(1,10); 15 | 16 | ps.execute(); 17 | 18 | 19 | // Update customers 20 | ps = conn.prepareStatement("UPDATE CUSTOMER SET STATE = lower(STATE)"); 21 | ps.execute(); 22 | 23 | // Iterate customers 24 | ResultSet rs = conn.prepareStatement("SELECT * FROM CUSTOMER").executeQuery(); 25 | 26 | while (rs.next()) { 27 | System.out.println(rs.getString("CUSTOMER_ID") + " " + rs.getString("CUSTOMER_NAME") + " " + rs.getString("STATE")); 28 | } 29 | 30 | // Update customers 31 | ps = conn.prepareStatement("UPDATE CUSTOMER SET STATE = upper(STATE)"); 32 | ps.execute(); 33 | 34 | //release connection 35 | conn.close(); 36 | 37 | } catch (Exception e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /code/section_iii/3_5_update_and_delete.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 4 | conn = engine.connect() 5 | 6 | # DELETE records 7 | deleteStmt = text("DELETE FROM CUSTOMER WHERE CUSTOMER_ID > :id") 8 | conn.execute(deleteStmt, id=10) 9 | print("Records deleted") 10 | 11 | # UPDATE records 12 | updateStmt = text("UPDATE CUSTOMER SET STATE = lower(STATE)") 13 | conn.execute(updateStmt) 14 | print("Records updated, STATE made lowercase") 15 | 16 | # SELECT records to check them 17 | for r in conn.execute(text("SELECT * FROM CUSTOMER")): 18 | print(r) 19 | 20 | # UPDATE records, make STATE UPPERCASE again 21 | updateStmt = text("UPDATE CUSTOMER SET STATE = upper(STATE)") 22 | conn.execute(updateStmt) 23 | 24 | 25 | conn.close() -------------------------------------------------------------------------------- /code/section_iii/3_6_successful_transaction.R: -------------------------------------------------------------------------------- 1 | 2 | library(DBI) 3 | library(RSQLite) 4 | 5 | db <- dbConnect(SQLite(), dbname='thunderbird_manufacturing.db') 6 | 7 | # Three new records in a DataFrame to insert 8 | 9 | new_records = data.frame( 10 | "CUSTOMER_NAME" = c("Zeta LLC", "Iota Construction", "Beta Solutions LTD"), 11 | "ADDRESS" = c("653 Kimberly Way", "12 Roth Road", "6742 Preston Rd"), 12 | "CITY" = c("Allen","Plano","Frisco"), 13 | "STATE" = c("TX","TX","TX"), 14 | "ZIP" = c(75032, 75035, 75002), 15 | "CATEGORY" = c("COMMERCIAL","INDUSTRIAL","COMMERCIAL") 16 | ) 17 | 18 | # Appends records to existing table 19 | # If table did not exist, it would create it 20 | 21 | # Do operations within a transaction 22 | # If anything throws an error, it will roll back 23 | dbBegin(db) 24 | 25 | tryCatch({ 26 | dbWriteTable(db, name="CUSTOMER", new_records, append=T) 27 | dbCommit(db) 28 | }, 29 | error = function(error_condition) { 30 | dbRollback(db) 31 | } 32 | ) 33 | 34 | dbDisconnect(db) 35 | 36 | -------------------------------------------------------------------------------- /code/section_iii/3_6_successful_transaction.java: -------------------------------------------------------------------------------- 1 | import java.sql.*; 2 | 3 | public class JavaLauncher { 4 | 5 | public static void main(String[] args) { 6 | 7 | try { 8 | 9 | Object[][] newRecords = { 10 | {"Otter Antiques", "5732 Serenity Ln", "Addison", "TX", 75031, "COMMERCIAL"}, 11 | {"North Exa Energy", "67 Hearst Dr", "Plano", "TX", 75093, "INDUSTRIAL"}, 12 | {"City of Plano", "239 Plano Dr", "Plano", "TX", 75093, "GOVERNMENT"} 13 | }; 14 | 15 | //Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 16 | Connection conn = DriverManager.getConnection("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 17 | 18 | // turn on transactions 19 | conn.setAutoCommit(false); 20 | 21 | // Insert 3 customers 22 | PreparedStatement ps = conn.prepareStatement("INSERT INTO CUSTOMER (CUSTOMER_NAME, ADDRESS, CITY, STATE, ZIP, CATEGORY) VALUES (?,?,?,?,?,?)"); 23 | 24 | for (Object[] record : newRecords) { 25 | for (int i=1; i <= record.length; i++) { 26 | ps.setObject(i, record[i-1]); 27 | } 28 | ps.execute(); 29 | } 30 | 31 | // commit transactions 32 | conn.commit(); 33 | 34 | // Iterate customers 35 | ResultSet rs = conn.prepareStatement("SELECT * FROM CUSTOMER").executeQuery(); 36 | 37 | while (rs.next()) { 38 | System.out.println(rs.getString("CUSTOMER_ID") + " " + rs.getString("CUSTOMER_NAME") + " " + rs.getString("STATE")); 39 | } 40 | //release connection 41 | conn.close(); 42 | 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /code/section_iii/3_6_successful_transaction.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 4 | conn = engine.connect() 5 | 6 | new_records = [ 7 | ("Otter Antiques", "5732 Serenity Ln", "Addison", "TX", 75031, "COMMERCIAL"), 8 | ("North Exa Energy", "67 Hearst Dr", "Plano", "TX", 75093, "INDUSTRIAL"), 9 | ("City of Plano", "239 Plano Dr", "Plano", "TX", 75093, "GOVERNMENT") 10 | ] 11 | 12 | # Start Transaction 13 | transaction = conn.begin() 14 | 15 | try: 16 | stmt = text( 17 | "INSERT INTO CUSTOMER (CUSTOMER_NAME, ADDRESS, CITY, STATE, ZIP, CATEGORY) VALUES (:customerName,:address,:city,:state,:zip,:category)") 18 | 19 | # Insert records, but they won't persist until transaction is finalized 20 | for new_record in new_records: 21 | conn.execute(stmt, customerName=new_record[0], 22 | address=new_record[1], 23 | city=new_record[2], 24 | state=new_record[3], 25 | zip=new_record[4], 26 | category=new_record[5] 27 | ) 28 | 29 | # Finalize transaction 30 | transaction.commit() 31 | 32 | except: 33 | print("Transaction failed! Rolling back") 34 | transaction.rollback() 35 | 36 | finally: 37 | conn.close() -------------------------------------------------------------------------------- /code/section_iii/3_7_failed_transaction.R: -------------------------------------------------------------------------------- 1 | 2 | library(DBI) 3 | library(RSQLite) 4 | 5 | db <- dbConnect(SQLite(), dbname='thunderbird_manufacturing.db') 6 | 7 | # Three new records in a DataFrame to insert 8 | 9 | new_records = data.frame( 10 | "CUSTOMER_NAME" = c("Zeta LLC", "Iota Construction", "Beta Solutions LTD"), 11 | "ADDRESS" = c("653 Kimberly Way", "12 Roth Road", "6742 Preston Rd"), 12 | "CITY" = c("Allen","Plano","Frisco"), 13 | "STATE" = c("TX","TX","TX"), 14 | "ZIP" = c(75032, 75035, 75002), 15 | "CATEGORY" = c("COMMERCIAL","INDUSTRIAL","COMMERCIAL") 16 | ) 17 | 18 | # Appends records to existing table 19 | # If table did not exist, it would create it 20 | 21 | # Do operations within a transaction 22 | # If anything throws an error, it will roll back 23 | dbBegin(db) 24 | 25 | tryCatch({ 26 | dbWriteTable(db, name="CUSTOMER", new_records, append=T) 27 | 28 | if (nrow(new_records) != 4) { 29 | stop("There are not 4 records!") 30 | } 31 | dbCommit(db) 32 | }, 33 | error = function(error_condition) { 34 | print(error_condition) 35 | dbRollback(db) 36 | } 37 | ) 38 | 39 | dbDisconnect(db) 40 | 41 | -------------------------------------------------------------------------------- /code/section_iii/3_7_failed_transaction.java: -------------------------------------------------------------------------------- 1 | import java.sql.*; 2 | 3 | public class JavaLauncher { 4 | 5 | public static void main(String[] args) { 6 | 7 | try { 8 | 9 | Object[][] newRecords = { 10 | {"Otter Antiques", "5732 Serenity Ln", "Addison", "TX", 75031, "COMMERCIAL"}, 11 | {"North Exa Energy", "67 Hearst Dr", "Plano", "TX", 75093, "INDUSTRIAL"}, 12 | {"City of Plano", "239 Plano Dr", "Plano", "TX" } // third item is missing data 13 | }; 14 | 15 | //Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 16 | Connection conn = DriverManager.getConnection("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 17 | 18 | // turn on transactions 19 | conn.setAutoCommit(false); 20 | 21 | // Insert 3 customers 22 | PreparedStatement ps = conn.prepareStatement("INSERT INTO CUSTOMER (CUSTOMER_NAME, ADDRESS, CITY, STATE, ZIP, CATEGORY) VALUES (?,?,?,?,?,?)"); 23 | 24 | try { 25 | for (Object[] record : newRecords) { 26 | if (record.length != 6) { 27 | throw new Exception("Fields are missing for record!"); 28 | } 29 | for (int i = 1; i <= record.length; i++) { 30 | ps.setObject(i, record[i - 1]); 31 | } 32 | ps.execute(); // this should fail on the third INSERT 33 | } 34 | 35 | // commit transactions 36 | conn.commit(); 37 | 38 | } catch(Exception e) { 39 | // roll back the transaction on failure 40 | conn.rollback(); 41 | throw e; 42 | } 43 | 44 | // Iterate customers 45 | ResultSet rs = conn.prepareStatement("SELECT * FROM CUSTOMER").executeQuery(); 46 | 47 | while (rs.next()) { 48 | System.out.println(rs.getString("CUSTOMER_ID") + " " + rs.getString("CUSTOMER_NAME") + " " + rs.getString("STATE")); 49 | } 50 | //release connection 51 | conn.close(); 52 | 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /code/section_iii/3_7_failed_transaction.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 4 | conn = engine.connect() 5 | 6 | new_records = [ 7 | ("Otter Antiques", "5732 Serenity Ln", "Addison", "TX", 75031, "COMMERCIAL"), 8 | ("North Exa Energy", "67 Hearst Dr", "Plano", "TX", 75093, "INDUSTRIAL"), 9 | ("City of Plano", "239 Plano Dr", "Plano", "TX", 75093) 10 | ] 11 | 12 | # Start Transaction 13 | transaction = conn.begin() 14 | 15 | try: 16 | stmt = text( 17 | "INSERT INTO CUSTOMER (CUSTOMER_NAME, ADDRESS, CITY, STATE, ZIP, CATEGORY) VALUES (:customerName,:address,:city,:state,:zip,:category)") 18 | 19 | # Insert records, but they won't persist until transaction is finalized 20 | for new_record in new_records: 21 | conn.execute(stmt, customerName=new_record[0], 22 | address=new_record[1], 23 | city=new_record[2], 24 | state=new_record[3], 25 | zip=new_record[4], 26 | category=new_record[5] 27 | ) 28 | 29 | # Finalize transaction 30 | transaction.commit() 31 | 32 | except: 33 | print("Transaction failed! Rolling back") 34 | transaction.rollback() 35 | 36 | finally: 37 | conn.close() -------------------------------------------------------------------------------- /code/section_iii/3_8_batch_insert.R: -------------------------------------------------------------------------------- 1 | 2 | library(DBI) 3 | library(RSQLite) 4 | 5 | db <- dbConnect(SQLite(), dbname='thunderbird_manufacturing.db') 6 | 7 | # Three new records in a DataFrame to insert 8 | new_records = data.frame( 9 | "CUSTOMER_NAME" = c("Zeta LLC", "Iota Construction", "Beta Solutions LTD"), 10 | "ADDRESS" = c("653 Kimberly Way", "12 Roth Road", "6742 Preston Rd"), 11 | "CITY" = c("Allen","Plano","Frisco"), 12 | "STATE" = c("TX","TX","TX"), 13 | "ZIP" = c(75032, 75035, 75002), 14 | "CATEGORY" = c("COMMERCIAL","INDUSTRIAL","COMMERCIAL") 15 | ) 16 | 17 | # Appends records to existing table 18 | # If table did not exist, it would create it 19 | dbWriteTable(db, name="CUSTOMER", new_records, append=T) 20 | 21 | dbDisconnect(db) 22 | 23 | -------------------------------------------------------------------------------- /code/section_iii/3_8_batch_insert.java: -------------------------------------------------------------------------------- 1 | import java.sql.*; 2 | 3 | public class JavaLauncher { 4 | 5 | public static void main(String[] args) { 6 | 7 | try { 8 | 9 | Object[][] newRecords = { 10 | {"Otter Antiques", "5732 Serenity Ln", "Addison", "TX", 75031, "COMMERCIAL"}, 11 | {"North Exa Energy", "67 Hearst Dr", "Plano", "TX", 75093, "INDUSTRIAL"}, 12 | {"City of Plano", "239 Plano Dr", "Plano", "TX", 75093, "GOVERNMENT"} 13 | }; 14 | 15 | //Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 16 | Connection conn = DriverManager.getConnection("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 17 | 18 | // turn on transactions 19 | conn.setAutoCommit(false); 20 | 21 | // Insert 2 customers at a time 22 | // Note in real life we probably would batch thousands of records at a time to help performance 23 | PreparedStatement ps = conn.prepareStatement("INSERT INTO CUSTOMER (CUSTOMER_NAME, ADDRESS, CITY, STATE, ZIP, CATEGORY) VALUES (?,?,?,?,?,?)"); 24 | 25 | for (int j=0; j < newRecords.length; j++) { 26 | Object[] newRecord = newRecords[j]; 27 | for (int i=0; i < newRecord.length; i++) { 28 | Object fieldValue = newRecord[i]; 29 | ps.setObject(i+1, fieldValue); 30 | } 31 | // batch the write operation 32 | ps.addBatch(); 33 | 34 | // if two records are batched, execute them 35 | if (j % 2 == 0) { 36 | ps.executeBatch(); 37 | } 38 | } 39 | 40 | // execute any remaining batch 41 | ps.executeBatch(); 42 | 43 | // commit transactions 44 | conn.commit(); 45 | 46 | // Iterate customers 47 | ResultSet rs = conn.prepareStatement("SELECT * FROM CUSTOMER").executeQuery(); 48 | 49 | while (rs.next()) { 50 | System.out.println(rs.getString("CUSTOMER_ID") + " " + rs.getString("CUSTOMER_NAME") + " " + rs.getString("STATE")); 51 | } 52 | 53 | //release connection 54 | conn.close(); 55 | 56 | } catch (Exception e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /code/section_iii/3_8_batch_insert.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | conn = sqlite3.connect('thunderbird_manufacturing.db') 4 | 5 | new_records = [ 6 | ("Otter Antiques", "5732 Serenity Ln", "Addison", "TX", 75031, "COMMERCIAL"), 7 | ("North Exa Energy", "67 Hearst Dr", "Plano", "TX", 75093, "INDUSTRIAL"), 8 | ("City of Plano", "239 Plano Dr", "Plano", "TX", 75093,"GOVERNMENT") 9 | ] 10 | 11 | # Batch insert all three records 12 | conn.executemany( 13 | "INSERT INTO CUSTOMER (CUSTOMER_NAME, ADDRESS, CITY, STATE, ZIP, CATEGORY) VALUES (?,?,?,?,?,?)", 14 | new_records) 15 | 16 | # Commit new records 17 | conn.commit() -------------------------------------------------------------------------------- /code/section_iii/3_9_dataframe_insert.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | import pandas as pd 3 | 4 | engine = create_engine('sqlite:///thunderbird_manufacturing.db') 5 | conn = engine.connect() 6 | 7 | 8 | df = pd.DataFrame(data=[ 9 | ("Otter Antiques", "5732 Serenity Ln", "Addison", "TX", 75031, "COMMERCIAL"), 10 | ("North Exa Energy", "67 Hearst Dr", "Plano", "TX", 75093, "INDUSTRIAL"), 11 | ("City of Plano", "239 Plano Dr", "Plano", "TX", 75093,"GOVERNMENT") 12 | ], 13 | columns=["CUSTOMER_NAME","ADDRESS","CITY","STATE","ZIP","CATEGORY"] 14 | ) 15 | 16 | df.to_sql("CUSTOMER", 17 | conn, 18 | if_exists="append", 19 | index=False) -------------------------------------------------------------------------------- /code/section_iii/thunderbird_manufacturing.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasnield/oreilly_programming_with_sql/ef673d38795ebd2bfac73b1fe92613ef0f3fbcab/code/section_iii/thunderbird_manufacturing.db -------------------------------------------------------------------------------- /code/section_iv/4_1_pooling.R: -------------------------------------------------------------------------------- 1 | 2 | # Pooling database connections in R 3 | # Documentation: https://cran.r-project.org/web/packages/pool/pool.pdf 4 | 5 | library(DBI) 6 | library(RSQLite) 7 | library(pool) 8 | 9 | # Instead of creating a connection, we create a pool of connections 10 | pool <- dbPool( 11 | drv = RSQLite::SQLite(), 12 | dbname = "thunderbird_manufacturing.db", 13 | minSize = 2, 14 | maxSize = 10, 15 | idleTimeout = 30 16 | # host = "someserver.somewhere.com", 17 | # username = "guest", 18 | # password = "guest" 19 | ) 20 | 21 | conn = poolCheckout(pool) 22 | my_query <- dbSendQuery(conn, "SELECT * FROM CUSTOMER") 23 | my_data <- dbFetch(my_query, n = -1) 24 | dbClearResult(my_query) 25 | 26 | print(my_data) 27 | poolReturn(conn) 28 | 29 | -------------------------------------------------------------------------------- /code/section_iv/4_1_pooling.java: -------------------------------------------------------------------------------- 1 | import com.zaxxer.hikari.HikariConfig; 2 | import com.zaxxer.hikari.HikariDataSource; 3 | 4 | import java.sql.Connection; 5 | import java.sql.DriverManager; 6 | import java.sql.ResultSet; 7 | import java.sql.Statement; 8 | 9 | public class JavaLauncher { 10 | 11 | public static void main(String[] args) { 12 | 13 | try { 14 | HikariConfig config = new HikariConfig(); 15 | //config.setJdbcUrl("jdbc:sqlite://C:/git/oreilly_programming_with_sql/thunderbird_manufacturing.db"); 16 | config.setJdbcUrl("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 17 | 18 | config.setMinimumIdle(1); 19 | config.setMaximumPoolSize(5); 20 | 21 | HikariDataSource ds = new HikariDataSource(config); 22 | 23 | // Get a connection from the pool 24 | Connection conn = ds.getConnection(); 25 | 26 | Statement stmt = conn.createStatement(); 27 | 28 | ResultSet rs = stmt.executeQuery("SELECT * FROM CUSTOMER"); 29 | 30 | while (rs.next()) { 31 | System.out.println(rs.getInt("CUSTOMER_ID") + " " + rs.getString("CUSTOMER_NAME")); 32 | } 33 | //release connection 34 | conn.close(); 35 | 36 | } catch (Exception e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /code/section_iv/4_1_pooling.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | # Connection pooling 4 | # Documentation: https://docs.sqlalchemy.org/en/13/core/pooling.html#api-documentation-available-pool-implementations 5 | from sqlalchemy.pool import QueuePool 6 | 7 | # pool_size - The number of connections to always have on hand 8 | # max_overflow - the max number of connections beyond the pool_size 9 | engine = create_engine('sqlite:///thunderbird_manufacturing.db', poolclass=QueuePool, pool_size=1, max_overflow=9) 10 | 11 | # Query and iterate customers 12 | conn = engine.connect() 13 | stmt = text("SELECT * FROM CUSTOMER") 14 | 15 | results = conn.execute(stmt) 16 | 17 | for r in results: 18 | print(r) 19 | 20 | 21 | conn.close() # return connection to pool 22 | -------------------------------------------------------------------------------- /code/section_iv/4_2_pooling_and_concurrency.java: -------------------------------------------------------------------------------- 1 | import com.zaxxer.hikari.HikariConfig; 2 | import com.zaxxer.hikari.HikariDataSource; 3 | 4 | import java.sql.Connection; 5 | import java.sql.DriverManager; 6 | import java.sql.ResultSet; 7 | import java.sql.Statement; 8 | import java.util.concurrent.Callable; 9 | import java.util.concurrent.ExecutorService; 10 | import java.util.concurrent.Executors; 11 | 12 | public class JavaLauncher { 13 | 14 | public static void main(String[] args) { 15 | 16 | try { 17 | HikariConfig config = new HikariConfig(); 18 | //config.setJdbcUrl("jdbc:sqlite://C:/git/oreilly_programming_with_sql/thunderbird_manufacturing.db"); 19 | config.setJdbcUrl("jdbc:sqlite:///Users/thomasnield/git/oreilly_intermediate_sql_for_data/thunderbird_manufacturing.db"); 20 | 21 | config.setMinimumIdle(1); 22 | config.setMaximumPoolSize(5); 23 | 24 | final HikariDataSource ds = new HikariDataSource(config); 25 | 26 | Runnable task1 = () -> { 27 | try { 28 | // Get a connection from the pool 29 | Connection conn = ds.getConnection(); 30 | 31 | Statement stmt = conn.createStatement(); 32 | 33 | ResultSet rs = stmt.executeQuery("SELECT * FROM CUSTOMER"); 34 | 35 | while (rs.next()) { 36 | System.out.println("QUERY 1: " + rs.getInt("CUSTOMER_ID") + " " + rs.getString("CUSTOMER_NAME")); 37 | } 38 | //release connection 39 | conn.close(); 40 | } catch (Exception e) { 41 | throw new RuntimeException(e); 42 | } 43 | }; 44 | Runnable task2 = () -> { 45 | try { 46 | // Get a connection from the pool 47 | Connection conn = ds.getConnection(); 48 | 49 | Statement stmt = conn.createStatement(); 50 | 51 | ResultSet rs = stmt.executeQuery("SELECT * FROM PRODUCT"); 52 | 53 | while (rs.next()) { 54 | System.out.println("QUERY 2: " + rs.getInt("PRODUCT_ID") + " " + rs.getString("PRODUCT_NAME")); 55 | } 56 | //release connection 57 | conn.close(); 58 | } catch (Exception e) { 59 | throw new RuntimeException(e); 60 | } 61 | }; 62 | 63 | // Create executor service with 2 threads 64 | // Schedule both tasks and shutdown when they are complete 65 | // We should see both sets of records iterated simultaneously 66 | ExecutorService exec = Executors.newFixedThreadPool(2); 67 | exec.submit(task1); 68 | exec.submit(task2); 69 | exec.shutdown(); 70 | 71 | } catch (Exception e) { 72 | e.printStackTrace(); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /code/section_iv/4_2_pooling_and_concurrency.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | from threading import Thread 3 | 4 | # Connection pooling 5 | # Documentation: https://docs.sqlalchemy.org/en/13/core/pooling.html#api-documentation-available-pool-implementations 6 | from sqlalchemy.pool import QueuePool 7 | 8 | # pool_size - The number of connections to always have on hand 9 | # max_overflow - the max number of connections beyond the pool_size 10 | # poolclass - the type of pool to use 11 | # timeout - the number of seconds to wait for a connection to be available before giving up 12 | engine = create_engine('sqlite:///thunderbird_manufacturing.db', poolclass=QueuePool, pool_size=1, max_overflow=9) 13 | 14 | # Here we kick off two queries simultaneously 15 | # Where each gets its own connection from the pool, 16 | # And returns it to the pool when done 17 | def query_customers(): 18 | conn = engine.connect() 19 | stmt = text("SELECT * FROM CUSTOMER") 20 | results = conn.execute(stmt) 21 | for r in results: 22 | print(r) 23 | conn.close() # return connection to pool 24 | 25 | 26 | def query_products(): 27 | conn = engine.connect() 28 | stmt = text("SELECT * FROM PRODUCT") 29 | results = conn.execute(stmt) 30 | for r in results: 31 | print(r) 32 | conn.close() # return connection to pool 33 | 34 | # Call the two functions from two separate threads 35 | thread1 = Thread(target=query_customers) 36 | thread2 = Thread(target=query_products) 37 | 38 | # Start and wait for the threads to finish 39 | thread1.start() 40 | thread2.start() 41 | thread1.join() 42 | thread2.join() 43 | -------------------------------------------------------------------------------- /code/section_iv/4_3_pooling_transaction.R: -------------------------------------------------------------------------------- 1 | 2 | # Pooling database connections in R 3 | # Documentation: https://cran.r-project.org/web/packages/pool/pool.pdf 4 | 5 | library(DBI) 6 | library(RSQLite) 7 | library(pool) 8 | 9 | # Instead of creating a connection, we create a pool of connections 10 | pool <- dbPool( 11 | drv = RSQLite::SQLite(), 12 | dbname = "thunderbird_manufacturing.db", 13 | minSize = 2, 14 | maxSize = 10, 15 | idleTimeout = 30 16 | # host = "someserver.somewhere.com", 17 | # username = "guest", 18 | # password = "guest" 19 | ) 20 | 21 | poolWithTransaction(pool, function(conn) { 22 | new_record = c("Brittania Solutions, LLC", "2374 Collie Way","Frisco","TX",75035,"COMMERCIAL") 23 | my_insert <- "INSERT INTO CUSTOMER (CUSTOMER_NAME, ADDRESS, CITY, STATE, ZIP, CATEGORY) VALUES (?,?,?,?,?,?)" 24 | dbExecute(conn, my_insert, params= new_record) 25 | }) 26 | 27 | # View all records in CUSTOMER to see if new record was added 28 | conn = poolCheckout(pool) 29 | my_query <- dbSendQuery(conn, "SELECT * FROM CUSTOMER") 30 | my_data <- dbFetch(my_query, n = -1) 31 | dbClearResult(my_query) 32 | 33 | print(my_data) 34 | poolReturn(conn) 35 | 36 | -------------------------------------------------------------------------------- /code/section_iv/4_4_connection_releasing.R: -------------------------------------------------------------------------------- 1 | 2 | library(DBI) 3 | library(RSQLite) 4 | 5 | db <- dbConnect(SQLite(), dbname='thunderbird_manufacturing.db') 6 | 7 | # use try-catch-finally to handle errors 8 | # and always release connection even if error occured 9 | tryCatch({ 10 | my_query <- dbSendQuery(db, "SELECT * FROM CUSTOMER") 11 | my_data <- dbFetch(my_query, n = -1) 12 | 13 | dbClearResult(my_query) 14 | print(my_data) 15 | remove(my_query) 16 | }, 17 | error = function(error_condition) { 18 | print(error_condition) 19 | }, 20 | finally = function() { 21 | dbDisconnect(db) 22 | } 23 | ) 24 | 25 | -------------------------------------------------------------------------------- /code/section_iv/4_4_connection_releasing.java: -------------------------------------------------------------------------------- 1 | import com.zaxxer.hikari.HikariConfig; 2 | import com.zaxxer.hikari.HikariDataSource; 3 | 4 | import java.sql.Connection; 5 | import java.sql.ResultSet; 6 | import java.sql.SQLException; 7 | import java.sql.Statement; 8 | 9 | public class JavaLauncher { 10 | 11 | public static void main(String[] args) throws SQLException { 12 | Connection conn = null; 13 | 14 | try { 15 | HikariConfig config = new HikariConfig(); 16 | config.setJdbcUrl("jdbc:sqlite://C:/git/oreilly_programming_with_sql/thunderbird_manufacturing.db"); 17 | config.setMinimumIdle(1); 18 | config.setMaximumPoolSize(5); 19 | 20 | final HikariDataSource ds = new HikariDataSource(config); 21 | conn = ds.getConnection(); 22 | 23 | Statement stmt = conn.createStatement(); 24 | ResultSet rs = stmt.executeQuery("SELECT * FROM PRODUCT"); 25 | 26 | while (rs.next()) { 27 | System.out.println(rs.getInt("PRODUCT_ID") + " " + rs.getString("PRODUCT_NAME")); 28 | } 29 | } catch (Exception e) { 30 | e.printStackTrace(); 31 | } finally { 32 | //release connection even if error occurred 33 | if (conn != null) { 34 | conn.close(); 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /code/section_iv/4_4_connection_releasing.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine, text 2 | 3 | # Connection pooling 4 | # Documentation: https://docs.sqlalchemy.org/en/13/core/pooling.html#api-documentation-available-pool-implementations 5 | from sqlalchemy.pool import QueuePool 6 | 7 | # pool_size - The number of connections to always have on hand 8 | # max_overflow - the max number of connections beyond the pool_size 9 | engine = create_engine('sqlite:///thunderbird_manufacturing.db', poolclass=QueuePool, pool_size=1, max_overflow=9) 10 | 11 | try: 12 | # Query and iterate customers 13 | conn = engine.connect() 14 | stmt = text("SELECT * FROM CUSTOMER") 15 | 16 | results = conn.execute(stmt) 17 | 18 | for r in results: 19 | print(r) 20 | except Exception as e: 21 | print("There was an error: {0}".format(e)) 22 | finally: 23 | conn.close() # return connection to pool, regardless if error occurred or not -------------------------------------------------------------------------------- /code/section_iv/4_5_try_with_resources.java: -------------------------------------------------------------------------------- 1 | import com.zaxxer.hikari.HikariConfig; 2 | import com.zaxxer.hikari.HikariDataSource; 3 | 4 | import java.sql.Connection; 5 | import java.sql.ResultSet; 6 | import java.sql.SQLException; 7 | import java.sql.Statement; 8 | 9 | public class JavaLauncher { 10 | 11 | public static void main(String[] args) { 12 | 13 | HikariConfig config = new HikariConfig(); 14 | config.setJdbcUrl("jdbc:sqlite://C:/git/oreilly_programming_with_sql/thunderbird_manufacturing.db"); 15 | config.setMinimumIdle(1); 16 | config.setMaximumPoolSize(5); 17 | 18 | final HikariDataSource ds = new HikariDataSource(config); 19 | 20 | // use try-catch with resources 21 | // this will automatically handle the disposal of resources 22 | // like connections and result sets 23 | // even when errors happen 24 | try(final Connection conn = ds.getConnection()) { 25 | 26 | Statement stmt = conn.createStatement(); 27 | try(ResultSet rs = stmt.executeQuery("SELECT * FROM PRODUCT")) { 28 | while (rs.next()) { 29 | System.out.println(rs.getInt("PRODUCT_ID") + " " + rs.getString("PRODUCT_NAME")); 30 | } 31 | } 32 | } catch (Exception e) { 33 | e.printStackTrace(); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /code/section_iv/thunderbird_manufacturing.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasnield/oreilly_programming_with_sql/ef673d38795ebd2bfac73b1fe92613ef0f3fbcab/code/section_iv/thunderbird_manufacturing.db -------------------------------------------------------------------------------- /oreilly_programming_with_sql.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasnield/oreilly_programming_with_sql/ef673d38795ebd2bfac73b1fe92613ef0f3fbcab/oreilly_programming_with_sql.pdf -------------------------------------------------------------------------------- /oreilly_programming_with_sql.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasnield/oreilly_programming_with_sql/ef673d38795ebd2bfac73b1fe92613ef0f3fbcab/oreilly_programming_with_sql.pptx -------------------------------------------------------------------------------- /thunderbird_manufacturing.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasnield/oreilly_programming_with_sql/ef673d38795ebd2bfac73b1fe92613ef0f3fbcab/thunderbird_manufacturing.db --------------------------------------------------------------------------------