├── .gitignore ├── .streamlit └── config.toml ├── Dockerfile ├── README.md ├── app.py ├── ecommerce_platform1.db ├── requirements.txt └── test.py /.gitignore: -------------------------------------------------------------------------------- 1 | .env -------------------------------------------------------------------------------- /.streamlit/config.toml: -------------------------------------------------------------------------------- 1 | [theme] 2 | base="light" -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the official Python image as the base image 2 | FROM python:3.10.13-slim 3 | 4 | # Set the working directory in the Docker container 5 | WORKDIR /app 6 | 7 | # Copy the requirements file into the container 8 | COPY requirements.txt requirements.txt 9 | 10 | # Install the Python dependencies 11 | RUN pip install --no-cache-dir -r requirements.txt 12 | 13 | # Copy the rest of the application's code into the container 14 | COPY . . 15 | 16 | # Expose the port the app runs on 17 | EXPOSE 8501 18 | 19 | # Command to run the app 20 | CMD ["streamlit", "run", "app.py"] 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Natural Language to SQL(Na2SQL): Extracting Insights from Databases using OpenaAI GPT3.5 and Llamaindex 2 | 3 | Welcome to the Natural Language to SQL demo project using LlamaIndex! This application is designed to demonstrate the innovative use of Large Language Models (LLMs) in translating natural language queries into SQL queries, and fetching meaningful insights from a database. 4 | 5 | ### Demo Features 6 | - **Natural Language Understanding**: Converts user-inputted natural language queries into accurate SQL queries. 7 | - **Data Retrieval and Analysis**: Retrieves results from the database and interprets them to provide meaningful insights. 8 | - **Accessibility**: Designed for users with no SQL background to easily interact with and extract insights from databases. 9 | 10 | ### Potential Enhancements 11 | - Expansion to include more diverse data sources and databases. 12 | - Advanced natural language processing for more intricate query handling. 13 | 14 | ### [Try the demo here!](https://na2sql.streamlit.app) 15 | 16 | ## Tools and Technologies Used 17 | - **LLM**: OpenAI's GPT-3.5 18 | - **LLM Orchestration**: LlamaIndex 19 | - **Data Management**: SQLDatabase with SQLite 20 | - **UI Framework**: Streamlit 21 | 22 | ## Project Structure 23 | - `app.py`: The main application script for the Streamlit app. 24 | - `requirements.txt`: Lists the Python packages required for this project. 25 | - `storage/`: Directory contains the database file and related resources. 26 | 27 | ## Setup and Usage 28 | ### Clone the Repository 29 | ```git clone https://github.com/YourGitHubUsername/your-repository-name``` 30 | ### Install Required Packages 31 | ```pip install -r requirements.txt``` 32 | ### Run the Streamlit App 33 | ```streamlit run app.py``` 34 | 35 | 36 | ## Feedback and Contributions 37 | Feel free to raise issues or submit pull requests if you think something can be improved or added. Your feedback is highly appreciated! 38 | 39 | ### Developed by [Harshad Suryawanshi](https://www.linkedin.com/in/harshadsuryawanshi/) 40 | If you find this project useful, consider giving it a ⭐ on GitHub! 41 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | from sqlalchemy import create_engine, inspect, text 3 | from typing import Dict, Any 4 | 5 | from llama_index.core import ( 6 | VectorStoreIndex, 7 | ServiceContext, 8 | download_loader, 9 | ) 10 | from llama_index.core import Settings 11 | 12 | from llama_index.core.llama_pack import BaseLlamaPack 13 | from llama_index.llms.openai import OpenAI 14 | import openai 15 | import os 16 | import pandas as pd 17 | from streamlit_pills import pills 18 | from PIL import Image 19 | 20 | 21 | # from llama_index.llms.palm import PaLM 22 | 23 | 24 | from llama_index.core import ( 25 | SimpleDirectoryReader, 26 | ServiceContext, 27 | StorageContext, 28 | VectorStoreIndex, 29 | load_index_from_storage, 30 | ) 31 | import sqlite3 32 | 33 | 34 | from llama_index.core import SQLDatabase, ServiceContext 35 | 36 | from llama_index.core.query_engine import NLSQLTableQueryEngine 37 | 38 | #os.environ['OPENAI_API_KEY'] = st.secrets['OPENAI_API_KEY'] 39 | 40 | 41 | class StreamlitChatPack(BaseLlamaPack): 42 | 43 | def __init__( 44 | self, 45 | page: str = "Natural Language to SQL Query", 46 | run_from_main: bool = False, 47 | **kwargs: Any, 48 | ) -> None: 49 | """Init params.""" 50 | 51 | self.page = page 52 | 53 | def get_modules(self) -> Dict[str, Any]: 54 | """Get modules.""" 55 | return {} 56 | 57 | def run(self, *args: Any, **kwargs: Any) -> Any: 58 | """Run the pipeline.""" 59 | import streamlit as st 60 | 61 | st.set_page_config( 62 | page_title=f"{self.page}", 63 | layout="centered", 64 | initial_sidebar_state="auto", 65 | menu_items=None, 66 | ) 67 | 68 | # Load your image 69 | image = Image.open('logo.png') 70 | # Display the image in the sidebar at the top left 71 | st.sidebar.image(image, width=70) 72 | 73 | if "messages" not in st.session_state: # Initialize the chat messages history 74 | st.session_state["messages"] = [ 75 | {"role": "assistant", "content": f"Hello. Ask me anything related to the database."} 76 | ] 77 | 78 | st.title( 79 | f"{self.page}💬" 80 | ) 81 | st.info( 82 | f"Explore Snowflake views with this AI-powered app. Pose any question and receive exact SQL queries.", 83 | icon="ℹ️", 84 | ) 85 | # Define the pills with emojis 86 | query_options = ["None", "In a markdown table format show which users bought '4K LED Smart TV', their purchase date and their location", "In a markdown table show all the products bought under books category and their reviews", "Analyse all the reviews for Electronics category and list points of improvements in a table"] 87 | # emojis = ["👥", "📅", "🏷️"] 88 | selected_query = pills("Select example queries or enter your own query in the chat input below", query_options, key="query_pills") 89 | 90 | def add_to_message_history(role, content): 91 | message = {"role": role, "content": str(content)} 92 | st.session_state["messages"].append( 93 | message 94 | ) # Add response to message history 95 | 96 | def get_table_data(table_name, conn): 97 | query = f"SELECT * FROM {table_name}" 98 | df = pd.read_sql_query(query, conn) 99 | return df 100 | 101 | #@st.cache_resource 102 | def load_db_llm(): 103 | # Load the SQLite database 104 | #engine = create_engine("sqlite:///ecommerce_platform1.db") 105 | engine = create_engine("sqlite:///ecommerce_platform1.db?mode=ro", connect_args={"uri": True}) 106 | 107 | sql_database = SQLDatabase(engine) #include all tables 108 | 109 | # Initialize LLM 110 | #llm2 = PaLM(api_key=os.environ["GOOGLE_API_KEY"]) # Replace with your API key 111 | Settings.llm = OpenAI(temperature=0.1, model="gpt-3.5-turbo-1106") 112 | 113 | #Settings.embed_model = "local:BAAI/bge-base-en-v1.5" 114 | 115 | return sql_database, Settings, engine 116 | 117 | sql_database, service_context, engine = load_db_llm() 118 | 119 | 120 | # Sidebar for database schema viewer 121 | st.sidebar.markdown("## Database Schema Viewer") 122 | 123 | # Create an inspector object 124 | inspector = inspect(engine) 125 | 126 | # Get list of tables in the database 127 | table_names = inspector.get_table_names() 128 | 129 | # Sidebar selection for tables 130 | selected_table = st.sidebar.selectbox("Select a Table", table_names) 131 | 132 | db_file = 'ecommerce_platform1.db' 133 | conn = sqlite3.connect(db_file) 134 | 135 | # Display the selected table 136 | if selected_table: 137 | df = get_table_data(selected_table, conn) 138 | st.sidebar.text(f"Data for table '{selected_table}':") 139 | st.sidebar.dataframe(df) 140 | 141 | # Close the connection 142 | conn.close() 143 | 144 | st.sidebar.markdown('## Disclaimer') 145 | st.sidebar.markdown("""This application is for demonstration purposes only and may not cover all aspects of real-world data complexities. Please use it as a guide and not as a definitive source for decision-making.""") 146 | 147 | if "query_engine" not in st.session_state: # Initialize the query engine 148 | st.session_state["query_engine"] = NLSQLTableQueryEngine( 149 | sql_database=sql_database, 150 | synthesize_response=True, 151 | service_context=service_context 152 | ) 153 | 154 | for message in st.session_state["messages"]: # Display the prior chat messages 155 | with st.chat_message(message["role"]): 156 | st.write(message["content"]) 157 | 158 | # Always show the chat input 159 | prompt = st.chat_input("Enter your natural language query about the database") 160 | 161 | # If a pill is selected, override the chat input with the pill's value 162 | if selected_query and selected_query!="None": 163 | prompt = selected_query 164 | 165 | # Handle the prompt logic 166 | if prompt: 167 | with st.chat_message("user"): 168 | st.write(prompt) 169 | add_to_message_history("user", prompt) 170 | 171 | # If last message is not from assistant, generate a new response 172 | if st.session_state["messages"][-1]["role"] != "assistant": 173 | with st.spinner(): 174 | with st.chat_message("assistant"): 175 | response = st.session_state["query_engine"].query("User Question:"+prompt+". ") 176 | sql_query = f"```sql\n{response.metadata['sql_query']}\n```\n**Response:**\n{response.response}\n" 177 | response_container = st.empty() 178 | response_container.write(sql_query) 179 | # st.write(response.response) 180 | add_to_message_history("assistant", sql_query) 181 | 182 | if __name__ == "__main__": 183 | StreamlitChatPack(run_from_main=True).run() 184 | -------------------------------------------------------------------------------- /ecommerce_platform1.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AI-ANK/Na2SQL/33441e9516abba7f3cc599b78e6d3edf9d8bc337/ecommerce_platform1.db -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | streamlit-pills==0.3.0 2 | streamlit==1.32.2 3 | SQLAlchemy==2.0.29 4 | openai==1.16.1 5 | llama-index==0.10.26 6 | google-generativeai==0.4.1 -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | import pandas as pd 3 | 4 | def get_table_data(table_name, conn): 5 | query = f"SELECT * FROM {table_name}" 6 | df = pd.read_sql_query(query, conn) 7 | return df 8 | 9 | db_file = 'ecommerce_platform1.db' 10 | conn = sqlite3.connect(db_file) 11 | 12 | # Display the selected table 13 | df = get_table_data('ShippingDetails', conn) 14 | print(f"df:{df}") 15 | 16 | # Add new users 17 | # import sqlite3 18 | # import random 19 | # from datetime import datetime, timedelta 20 | 21 | # # Function to generate realistic and unique user data 22 | # def generate_unique_users(existing_users, count, domain="example.com"): 23 | # base_names = ["Sophia", "Emma", "Olivia", "Ava", "Isabella", "Mia", "Charlotte", "Amelia", "Harper", "Evelyn"] 24 | # last_names = ["Martinez", "Hernandez", "Lopez", "Gonzalez", "Sanchez", "Perez", "Garcia", "Rodriguez", "Lee", "Brown"] 25 | # existing_emails = {user[2] for user in existing_users} # Extract existing emails from the current data 26 | # new_users = [] 27 | 28 | # while len(new_users) < count: 29 | # first_name = random.choice(base_names) 30 | # last_name = random.choice(last_names) 31 | # email = f"{first_name.lower()}.{last_name.lower()}@{domain}" 32 | # # Ensure unique email 33 | # if email in existing_emails: 34 | # continue 35 | # existing_emails.add(email) 36 | 37 | # age = random.randint(22, 50) 38 | # registration_date = datetime.now() - timedelta(days=random.randint(1, 365 * 2)) 39 | # address = f"{random.randint(100, 999)} {random.choice(['Oak', 'Maple', 'Pine', 'Elm', 'Cedar'])} St, {random.choice(['Springfield', 'Riverside', 'Greenfield', 'Hilltown', 'Lakeview'])}" 40 | # postal_code = f"011{random.randint(10, 99)}" 41 | # new_users.append((first_name + " " + last_name, email, age, registration_date.strftime('%Y-%m-%d'), address, postal_code)) 42 | 43 | # return new_users 44 | 45 | # # Function to insert users into the database 46 | # def insert_users_into_db(db_path, new_users): 47 | # conn = sqlite3.connect(db_path) 48 | # cursor = conn.cursor() 49 | # cursor.executemany("INSERT INTO Users (Name, Email, Age, RegistrationDate, Address, PostalCode) VALUES (?, ?, ?, ?, ?, ?);", new_users) 50 | # conn.commit() 51 | # conn.close() 52 | 53 | # # Main process 54 | # def main(): 55 | # db_path = 'ecommerce_platform1.db' # Adjust this path to your database file location 56 | # conn = sqlite3.connect(db_path) 57 | # cursor = conn.cursor() 58 | # cursor.execute("SELECT * FROM Users;") 59 | # existing_users = cursor.fetchall() 60 | # conn.close() 61 | 62 | # # Generate and insert new users 63 | # new_users_count = 30 - len(existing_users) # Adjust the number as needed 64 | # new_users = generate_unique_users(existing_users, new_users_count) 65 | # insert_users_into_db(db_path, new_users) 66 | 67 | # print(f"Added {len(new_users)} new users to the database.") 68 | 69 | # # Execute the program 70 | # if __name__ == "__main__": 71 | # main() 72 | 73 | # Add new orders 74 | # import sqlite3 75 | # import random 76 | # from datetime import datetime, timedelta 77 | 78 | # # Function to generate orders 79 | # def generate_orders(user_ids, product_prices, count): 80 | # orders = [] 81 | # for _ in range(count): 82 | # user_id = random.choice(user_ids) 83 | # order_date = datetime.now() - timedelta(days=random.randint(1, 365)) 84 | # # Simulating order with 1 to 5 products 85 | # products = random.choices(list(product_prices.keys()), k=random.randint(1, 5)) 86 | # total_amount = sum(product_prices[prod_id] for prod_id in products) 87 | # status = random.choice(['Pending', 'Shipped', 'Delivered', 'Cancelled']) 88 | # orders.append((user_id, order_date.strftime('%Y-%m-%d'), total_amount, status)) 89 | # return orders 90 | 91 | # # Function to insert orders into the database 92 | # def insert_orders_into_db(db_path, orders): 93 | # conn = sqlite3.connect(db_path) 94 | # cursor = conn.cursor() 95 | # cursor.executemany("INSERT INTO Orders (UserID, OrderDate, TotalAmount, Status) VALUES (?, ?, ?, ?);", orders) 96 | # conn.commit() 97 | # conn.close() 98 | 99 | # def main(): 100 | # db_path = 'ecommerce_platform1.db' # Adjust this path to your database file location 101 | 102 | # # Fetch existing user IDs and product prices 103 | # conn = sqlite3.connect(db_path) 104 | # cursor = conn.cursor() 105 | # cursor.execute("SELECT UserID FROM Users;") 106 | # user_ids = [row[0] for row in cursor.fetchall()] 107 | 108 | # cursor.execute("SELECT ProductID, Price FROM Products;") 109 | # product_prices = {row[0]: row[1] for row in cursor.fetchall()} 110 | # conn.close() 111 | 112 | # # Generate and insert new orders 113 | # new_orders = generate_orders(user_ids, product_prices, 20) # Number of orders to add 114 | # insert_orders_into_db(db_path, new_orders) 115 | 116 | # print(f"Added {len(new_orders)} new orders to the database.") 117 | 118 | # # Execute the program 119 | # if __name__ == "__main__": 120 | # main() 121 | 122 | 123 | # import sqlite3 124 | 125 | # # Replace 'your_database.db' with the path to your .db file 126 | # db_path = 'ecommerce_platform1.db' 127 | 128 | # # Connect to the SQLite database 129 | # conn = sqlite3.connect(db_path) 130 | # cursor = conn.cursor() 131 | 132 | # # Get a list of all tables in the database 133 | # cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") 134 | # tables = cursor.fetchall() 135 | 136 | # # Iterate through all tables 137 | # for table_name in tables: 138 | # print(f"Table: {table_name[0]}") 139 | # cursor.execute(f"SELECT * FROM `{table_name[0]}`") 140 | 141 | # # Get all columns in the table 142 | # columns = [description[0] for description in cursor.description] 143 | # print(f"Columns: {', '.join(columns)}") 144 | 145 | # # Fetch and print all rows of the table 146 | # rows = cursor.fetchall() 147 | # for row in rows: 148 | # print(row) 149 | 150 | # print() # Print a newline for better readability between tables 151 | 152 | # # Close the connection to the database 153 | # conn.close() 154 | 155 | 156 | # import sqlite3 157 | 158 | # # Connect to your SQLite database 159 | # conn = sqlite3.connect('ecommerce_platform1.db') # Replace 'your_database.db' with the path to your database file 160 | # cursor = conn.cursor() 161 | 162 | # # SQL statement to delete rows 163 | # delete_query = "DELETE FROM Orders WHERE OrderID > 20;" 164 | 165 | # # Execute the SQL statement 166 | # cursor.execute(delete_query) 167 | 168 | # # Commit the transaction 169 | # conn.commit() 170 | 171 | # # Close the database connection 172 | # conn.close() 173 | 174 | # import sqlite3 175 | 176 | # # Connect to your SQLite database 177 | # conn = sqlite3.connect('ecommerce_platform1.db') # Replace 'your_database.db' with the path to your database file 178 | # cursor = conn.cursor() 179 | 180 | # # SQL statement for inserting data 181 | # insert_query = """ 182 | # INSERT INTO Orders (UserID, OrderDate, TotalAmount, Status) 183 | # VALUES 184 | # (13, '2022-06-03', 105.97, 'Delivered'), 185 | # (19, '2022-06-05', 24.98, 'Shipped'), 186 | # (24, '2022-06-07', 179.98, 'Processing'), 187 | # (11, '2022-06-10', 28.98, 'Delivered'), 188 | # (26, '2022-06-12', 194.98, 'Processing'), 189 | # (15, '2022-06-15', 55.98, 'Shipped'), 190 | # (21, '2022-06-17', 44.98, 'Delivered'), 191 | # (17, '2022-06-19', 98.98, 'Processing'), 192 | # (22, '2022-06-22', 124.97, 'Shipped'), 193 | # (14, '2022-06-24', 22.99, 'Delivered'), 194 | # (29, '2022-06-26', 1499.99, 'Processing'), 195 | # (20, '2022-06-29', 34.98, 'Shipped'), 196 | # (25, '2022-07-01', 114.97, 'Delivered'), 197 | # (18, '2022-07-03', 64.98, 'Processing'), 198 | # (27, '2022-07-06', 210.98, 'Shipped'), 199 | # (23, '2022-07-08', 34.98, 'Delivered'), 200 | # (16, '2022-07-11', 135.97, 'Processing'), 201 | # (30, '2022-07-13', 254.97, 'Shipped'), 202 | # (28, '2022-07-16', 18.98, 'Delivered'), 203 | # (12, '2022-07-18', 45.99, 'Processing'); 204 | # """ 205 | 206 | # # Execute the SQL statement 207 | # cursor.execute(insert_query) 208 | 209 | # # Commit the transaction 210 | # conn.commit() 211 | 212 | # # Close the database connection 213 | # conn.close() 214 | 215 | 216 | #Add orderdetails 217 | # import sqlite3 218 | 219 | # # Connect to your SQLite database 220 | # conn = sqlite3.connect('ecommerce_platform1.db') # Replace 'your_database.db' with the path to your database file 221 | # cursor = conn.cursor() 222 | 223 | # # SQL statement for inserting data 224 | # insert_query = """ 225 | # INSERT INTO OrderDetails (OrderID, ProductID, Quantity, PricePerUnit) 226 | # VALUES 227 | # (21, 14, 5, 2.99), 228 | # (21, 13, 3, 5.99), 229 | # (22, 26, 2, 12.99), 230 | # (23, 21, 1, 199.99), 231 | # (23, 12, 1, 15.99), 232 | # (24, 15, 1, 12.99), 233 | # (24, 16, 1, 8.99), 234 | # (25, 5, 5, 19.99), 235 | # (25, 6, 3, 49.99), 236 | # (26, 29, 2, 15.99), 237 | # (26, 30, 1, 17.99), 238 | # (27, 20, 4, 9.99), 239 | # (28, 25, 2, 29.99), 240 | # (28, 26, 1, 12.99), 241 | # (29, 27, 1, 89.99), 242 | # (29, 28, 1, 24.99), 243 | # (30, 18, 1, 22.99), 244 | # (31, 1, 1, 1499.99), 245 | # (32, 29, 2, 15.99), 246 | # (33, 14, 4, 2.99), 247 | # (33, 13, 3, 5.99), 248 | # (34, 24, 4, 9.99), 249 | # (34, 23, 1, 45.99), 250 | # (35, 4, 3, 29.99), 251 | # (35, 3, 2, 14.99), 252 | # (36, 15, 1, 12.99), 253 | # (36, 16, 1, 8.99), 254 | # (37, 7, 1, 99.99), 255 | # (37, 8, 1, 149.99), 256 | # (38, 22, 1, 499.99), 257 | # (38, 19, 1, 19.99), 258 | # (39, 16, 2, 8.99), 259 | # (40, 23, 1, 45.99); 260 | # """ 261 | 262 | # # Execute the SQL statement 263 | # cursor.execute(insert_query) 264 | 265 | # # Commit the transaction 266 | # conn.commit() 267 | 268 | # # Close the database connection 269 | # conn.close() 270 | 271 | #add reviews 272 | 273 | # import sqlite3 274 | 275 | # # Connect to your SQLite database 276 | # # conn = sqlite3.connect('your_database.db') # Replace 'your_database.db' with the path to your database file 277 | # cursor = conn.cursor() 278 | 279 | # # SQL statement for inserting data 280 | # insert_query = """ 281 | # INSERT INTO Reviews (ProductID, UserID, Rating, Comment) 282 | # VALUES 283 | # (5, 25, 4, 'The T-shirts are comfortable and fit well. Good value for the price.'), 284 | # (6, 25, 5, 'Love these jeans! They''re stylish and well-made.'), 285 | # (14, 21, 3, 'The bread is tasty but it does get stale quickly as others have mentioned.'), 286 | # (13, 21, 5, 'This green tea is my new favorite! It''s so refreshing.'), 287 | # (20, 27, 4, 'Cute and sturdy flower pots, perfect for my herbs.'), 288 | # (4, 27, 5, 'This book was a great help in my Python programming course!'), 289 | # (23, 16, 4, 'My dog loves this food and it seems to be very healthy for him.'), 290 | # (24, 16, 3, 'The cat toy is okay, but my cat got bored with it quickly.'); 291 | # """ 292 | 293 | # # Execute the SQL statement 294 | # cursor.execute(insert_query) 295 | 296 | # # Commit the transaction 297 | # conn.commit() 298 | 299 | # # Close the database connection 300 | # conn.close() 301 | 302 | 303 | # import sqlite3 304 | 305 | # # Connect to your SQLite database 306 | # # conn = sqlite3.connect('your_database.db') # Replace 'your_database.db' with the path to your database file 307 | # cursor = conn.cursor() 308 | 309 | # # SQL statement for inserting data 310 | # insert_query = """ 311 | # INSERT INTO ShippingDetails (OrderID, ShippingAddress, EstimatedDeliveryDate, ActualDeliveryDate) 312 | # VALUES 313 | # (21, '579 Willow Way, Cliffside', '2022-06-08', '2022-06-07'), 314 | # (22, '965 Pine St, Springfield', '2022-06-10', '2022-06-09'), 315 | # (23, '117 Cedar St, Lakeview', '2022-06-12', NULL), 316 | # (24, '135 Oak Drive, Riverdale', '2022-06-15', '2022-06-14'), 317 | # (25, '268 Maple St, Hilltown', '2022-06-17', NULL), 318 | # (26, '902 Cedar Path, Mountainview', '2022-06-20', '2022-06-19'), 319 | # (27, '863 Pine St, Lakeview', '2022-06-22', '2022-06-21'), 320 | # (28, '217 Pine St, Hilltown', '2022-06-24', NULL), 321 | # (29, '675 Maple St, Lakeview', '2022-06-27', '2022-06-26'), 322 | # (30, '368 Elm Avenue, Lakeside', '2022-06-29', '2022-06-28'), 323 | # (31, '389 Maple St, Springfield', '2022-07-02', NULL), 324 | # (32, '376 Maple St, Greenfield', '2022-07-05', '2022-07-04'), 325 | # (33, '135 Elm St, Lakeview', '2022-07-07', '2022-07-06'), 326 | # (34, '887 Pine St, Lakeview', '2022-07-09', NULL), 327 | # (35, '975 Pine St, Hilltown', '2022-07-12', '2022-07-11'), 328 | # (36, '573 Elm St, Greenfield', '2022-07-14', '2022-07-13'), 329 | # (37, '435 Cedar St, Lakeview', '2022-07-16', NULL), 330 | # (38, '399 Maple St, Greenfield', '2022-07-18', '2022-07-17'), 331 | # (39, '221 Maple St, Hilltown', '2022-07-20', '2022-07-19'), 332 | # (40, '246 Pine Street, Brookside', '2022-07-22', NULL); 333 | # """ 334 | 335 | # # Execute the SQL statement 336 | # cursor.execute(insert_query) 337 | 338 | # # Commit the transaction 339 | # conn.commit() 340 | 341 | # # Close the database connection 342 | # conn.close() 343 | --------------------------------------------------------------------------------