Python

P
PythonHub
Progress 0%

Python

  • Home
  • History of Python
  • Applications of Python
  • Introduction To Python
    • What is Python
    • Character Set
    • Tokens in Python
    • Python Execution Mode
    • Variable And Identifiers
    • Data Types in Python
    • Operators And Expressions
    • Constants in Python
    • Assignment Statement
    • Input / Output in Python
    • Simple Python Scripts
    • Namespace in Python
    • šŸ“ Assignments
  • Operators in Python
    • Arithmetic Operators
    • Assignment Operators
    • Shorthand Assignment Operators
    • Relational Operators
    • Logical Operators
    • Bitwise Operators
    • Special Operators
    • šŸ“ Assignments
  • Input Output in Python
    • Accept Input
    • Output Formatting
    • šŸ“ Assignments
  • Conditional Statement
    • Decision Making
    • if Statement
    • IF-ELSE STATEMENT
    • IF-ELSE LADDER
    • NESTED IF-ELSE
    • Short Hand IF-ELSE
    • šŸ“ Assignments
  • Loops
    • Introduction to Loops
    • While Loop
    • Nested While Loop
    • šŸ“ While Loop Assignments
    • For Loop
    • For Loop Examples
    • Nested For Loop
    • Nested For Loop Examples
    • Infinite While Loops
    • Infinite For Loops
    • Break, Continue and Else in Loops
    • Difference Between For and While Loop
    • For Each Loop
    • šŸ“ For Each Assignments
    • šŸ“ All Loops Assignments
  • List
    • List in Python
    • Access List Elements
    • List Functions
    • Iterate (Loop) List
    • List Comprehension
    • šŸ“ Assignments
  • Tuple
    • Tuple in Python
    • Access Tuple Elements
    • Tuple Functions
    • Iterate (Loop) Tuple
    • Unpack Tuple
    • Tuple Comprehension
    • šŸ“ Assignments
  • Set
    • Set in Python
    • Access Set Elements
    • Set Methods
    • Iterate (Loop) Set
    • Pack/Unpack Set
    • Set Comprehension
    • šŸ“ Assignments
  • Dictionary
    • Dictionary
    • Access Dictionary Items
    • Dictionary Methods
    • Iterate (Loop) Dictionary
    • Formatting Dictionaries
    • Nested Dictionaries
    • Dictionary Comprehension
    • šŸ“ Assignments
  • Diff List Tuple Set Dictionary
    • List vs Tuple
    • List vs Set
    • List vs Dictionary
    • Tuple vs Set
    • Tuple vs Dictionary
    • Dictionary vs Set
    • šŸ“ Assignments
  • Exception
    • Error vs Exception
    • Types of Exception
    • Exception Handling
    • User Defined Exception
    • Logging Exception
    • šŸ“ Assignments
  • Functions
    • Introduction to Functions
    • Modular Programming
    • Types of Functions
    • Inbuilt Functions
    • Need For User-Defined Function
    • Elements of User Defined Function
    • Function Arguments
    • Nesting of Functions
    • Recursion
    • Global Local and Non Local
    • Python Lambda Functions
    • šŸ“ Assignments
  • Python Module
    • Introduction to Module
    • Inbuilt Modules in Python
    • User Defined Module
    • šŸ“ Assignments
  • File Handling
    • Introduction to Files
    • Create File
    • Read Files
    • Write to File
    • Rename File
    • Copy File
    • Move File
    • List Files in Directory
    • Binary Files
    • Zipping and Unzipping Files
    • šŸ“ Assignments
  • Strings
    • Basics of Strings
    • String Special Operators
    • String Formatting Operators
    • String Methods
    • šŸ“ Assignments
  • Regular Expressions
  • Python OOPS
    • Basics of Object Oriented
    • What are Classes and Objects?
    • Creating Class and Object
    • OOP vs Procedural Programming
    • Difference Between Classes and Objects
    • Constructors
    • Destructor
    • Built Class Methods and Attributes
    • Class and Instance Variables
    • Inheritance in Python
    • Single Inheritance
    • Multiple Inheritance
    • Multilevel Inheritance
    • Hierarchical Inheritance
    • Hybrid Inheritance
    • Abstraction
    • Method Overriding
    • Abstract Method
    • Interfaces in Python
    • Abstract Class vs Interface
    • Public, Private and Protected
    • Overloading vs Overriding
    • Inheritance vs Composition
    • Encapsulation
    • Polymorphism
    • Inner Classes
    • šŸ“ Assignments
  • Advanced Python
    • Iterator in Python
    • Generator in Python
    • Decorator in Python
    • Type Hints in Python
    • Async/Await Programming
    • Dataclasses in Python
    • Context Managers in Python
    • Property Decorator in Python
    • __slots__ in Python
    • Enums in Python
    • Walrus Operator in Python
    • Match-Case in Python
    • šŸ“ Assignments
  • Python Standard Library
    • Collections Module
    • Itertools Module
    • Functools Module
    • Datetime Module
    • JSON Module
    • OS Module
    • Sys Module
    • Random Module
    • Math Module
    • šŸ“ Assignments
  • Python Testing
    • Unit Testing in Python
    • Pytest Framework
    • Mocking in Python
    • šŸ“ Assignments
  • Python Best Practices
    • PEP 8 Style Guide
    • Docstrings in Python
    • Logging in Python
    • Code Optimization Tips
    • Debugging Techniques
    • šŸ“ Assignments
  • MySQL Database in Python
    • Introduction to MySQL with Python
    • DBMS vs File System
    • Connecting to MySQL Database
    • Create Database in MySQL
    • Create Table in MySQL
    • Insert Data in MySQL
    • Insert Multiple Rows
    • Select Data from MySQL
    • WHERE Clause in MySQL
    • Update Data in MySQL
    • Delete Data from MySQL
    • Parameterized Queries
    • Transaction Management
    • Error Handling
    • Connection Pooling
    • MySQL Drivers Guide
    • Joins in MySQL
    • Aggregation Functions
    • Backup MySQL Database
    • Best Practices
    • šŸ“ Assignments
  • MySQL Database Operations
    • SELECT Statement
    • MySQL Operators
    • DDL Statements
    • DML Statements
    • Subqueries
    • JOIN Operations
    • Aggregation
    • Case Study
    • šŸ“ Assignments
  • Graphics in Python
  • Threads in Python
    • Introduction to Threads
    • Process vs Threads
    • Concurrent Programming & GIL
    • Uses of Threads
    • Creating Threads
    • Single Tasking
    • Multi Tasking
    • Thread Synchronization
    • šŸ“ Assignments
  • Interview Questions & Answers
  • Python Case Studies
  • Multiple Choice Questions
  • šŸ“ Practice Problems
Get in Touch
  • tech2dsm@gmail.com

© Sankalan Data Tech

Python Language Interactive Tutorial

Python: Parameterized Queries

Python MySQL Parameterized Queries - Complete Guide

Learn how to use parameterized queries to keep your database safe.

Created by Sankalan Data Tech Team Verified
Data Engineers, Analysts, Scientists & Trainers
Created by experienced Python developers, data engineers, and data scientists to make programming easy through practical examples, real-world experience, and clear explanations.
On this page:
  • What are Parameterized Queries?
  • The Danger: SQL Injection
  • The Safe Way: Parameterized Queries
  • Examples for Every Operation
  • Real-World Example
  • Best Practices
  • Try It Yourself
  • Quiz
  • FAQ
Share this tutorial:
Twitter LinkedIn Facebook WhatsApp Reddit Telegram Email Copy Link
What You'll Learn Here
  • What are parameterized queries — the safe way to talk to databases
  • SQL Injection — the danger of unsafe queries
  • How to use parameterized queries — with real examples
  • Parameterized queries for all operations — SELECT, INSERT, UPDATE, DELETE
  • Best practices — keeping your code secure

What are Parameterized Queries?

A parameterized query is a way of writing SQL queries where you separate the SQL code from the data. Instead of putting user input directly into your query, you use placeholders and then provide the data separately.

šŸ’” Key concept: Think of it like a form with blank spaces. You write the form (SQL) with empty fields (placeholders), and then you fill in the blanks (data) separately. This keeps the data separate from the instructions.

Why is this important? Because it's the #1 way to prevent SQL injection attacks — one of the most common security threats to websites and applications.

1

What Makes a Query "Parameterized"?

# ============================================================
# WHAT DOES PARAMETERIZED MEAN?
# ============================================================

#  UNSAFE - Direct string concatenation
user_input = input("Enter your name: ")
query = f"SELECT * FROM users WHERE name = '{user_input}'"
cursor.execute(query)

#  SAFE - Parameterized query
user_input = input("Enter your name: ")
query = "SELECT * FROM users WHERE name = %s"
cursor.execute(query, (user_input,))

# ============================================================
# THE THREE KEY PARTS
# ============================================================

# 1. The SQL with placeholders (%s)
query = "SELECT * FROM students WHERE age > %s AND first_name = %s"

# 2. The data (as a tuple)
data = (18, "Rahul")

# 3. Execute with the data separately
cursor.execute(query, data)

# ============================================================
# WHY IT WORKS
# ============================================================

# The database sees:
# - The SQL structure (SELECT * FROM students WHERE age > ? AND first_name = ?)
# - The data separately (18, "Rahul")
# - It never mixes them together

Key point: Parameterized queries separate the SQL code from the data. The database knows exactly where the data ends and the code begins.

Quick Check: What is the main benefit of parameterized queries? (Answer: They prevent SQL injection attacks by separating SQL code from data)

The Danger: SQL Injection

2

What Happens When You're Not Careful

🚨 SQL Injection is a serious security vulnerability that allows attackers to execute malicious SQL code on your database. It can steal, modify, or delete your data.

# ============================================================
# THE PROBLEM WITH STRING CONCATENATION
# ============================================================

# Imagine this is your code
def get_user(name):
    # UNSAFE - Using string concatenation
    query = "SELECT * FROM users WHERE name = '" + name + "'"
    cursor.execute(query)
    return cursor.fetchall()

# ============================================================
# WHAT CAN GO WRONG
# ============================================================

# User enters: Rahul
# Query becomes: SELECT * FROM users WHERE name = 'Rahul'
#  Safe - Nothing wrong

# User enters: Rahul' OR '1'='1
# Query becomes: SELECT * FROM users WHERE name = 'Rahul' OR '1'='1'
#  DANGER! This returns ALL users!

# User enters: Rahul'; DROP TABLE users; --
# Query becomes: SELECT * FROM users WHERE name = 'Rahul'; DROP TABLE users; --'
#  DISASTER! The users table gets deleted!

# ============================================================
# HOW ATTACKERS EXPLOIT THIS
# ============================================================

print("""
Common SQL injection attacks:
1. Login bypass: ' OR '1'='1
2. Data theft: ' UNION SELECT * FROM passwords --
3. Data deletion: '; DROP TABLE users --
4. Data modification: '; UPDATE users SET admin=1 WHERE name='admin' --

šŸ’€ All of these can destroy your database!
""")

Why SQL injection is so dangerous:

  • It can steal sensitive data (passwords, credit cards)
  • It can delete your entire database
  • It can modify data without permission
  • It can bypass login systems
  • It's one of the most common web vulnerabilities

Quick Check: What is SQL injection? (Answer: A security attack where malicious SQL code is inserted into a query)

The Safe Way: Parameterized Queries

3

How Parameterized Queries Protect You

šŸ”’ Parameterized queries are the #1 defense against SQL injection. They completely separate code from data, making injection impossible.

# ============================================================
# THE SAFE WAY
# ============================================================

def get_user_safe(name):
    # SAFE - Using parameterized query
    query = "SELECT * FROM users WHERE name = %s"
    cursor.execute(query, (name,))
    return cursor.fetchall()

# ============================================================
# WHAT HAPPENS WITH PARAMETERIZED QUERIES
# ============================================================

# User enters: Rahul
# Data sent: ('Rahul',)
#  Finds the user named Rahul

# User enters: Rahul' OR '1'='1
# Data sent: ("Rahul' OR '1'='1",)
#  Finds NO user (searches for that exact name)
# The database treats it as TEXT, not as SQL code

# User enters: Rahul'; DROP TABLE users; --
# Data sent: ("Rahul'; DROP TABLE users; --",)
#  Finds NO user (searches for that exact name)
# The database treats it as TEXT, not as SQL code

# ============================================================
# COMPARISON
# ============================================================

print("""
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│ UNSAFE (String concat)  │ SAFE (Parameterized)        │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│ ' OR '1'='1             │ Search for exact name       │
│ → Returns ALL users     │ → Returns NO users          │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│ '; DROP TABLE users; -- │ Search for exact name       │
│ → Table DELETED!        │ → Table SAFE!               │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│ ' UNION SELECT * FROM   │ Search for exact name       │
│ passwords --            │ → Data SAFE!                │
│ → Data STOLEN!          │                             │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
""")

How parameterized queries work:

  • The SQL structure is sent to the database first
  • The data is sent separately
  • The database never interprets the data as SQL code
  • Even if data contains SQL commands, they're treated as text
  • This makes SQL injection impossible

Quick Check: How do parameterized queries protect against SQL injection? (Answer: By sending SQL code and data separately, so data is never treated as code)

Examples for Every Operation

4

Parameterized Queries for SELECT, INSERT, UPDATE, DELETE

# ============================================================
# SELECT - Reading data
# ============================================================

def get_students_by_age(min_age):
    query = "SELECT * FROM students WHERE age > %s"
    cursor.execute(query, (min_age,))
    return cursor.fetchall()

# Usage
students = get_students_by_age(18)

# ============================================================
# INSERT - Adding data
# ============================================================

def add_student(first_name, last_name, age, email):
    query = """
        INSERT INTO students (first_name, last_name, age, email)
        VALUES (%s, %s, %s, %s)
    """
    cursor.execute(query, (first_name, last_name, age, email))
    connection.commit()
    return cursor.lastrowid

# Usage
new_id = add_student("Rahul", "Sharma", 22, "rahul@email.com")

# ============================================================
# UPDATE - Modifying data
# ============================================================

def update_student_age(student_id, new_age):
    query = "UPDATE students SET age = %s WHERE student_id = %s"
    cursor.execute(query, (new_age, student_id))
    connection.commit()
    return cursor.rowcount

# Usage
rows_updated = update_student_age(1, 23)

# ============================================================
# DELETE - Removing data
# ============================================================

def delete_student(student_id):
    query = "DELETE FROM students WHERE student_id = %s"
    cursor.execute(query, (student_id,))
    connection.commit()
    return cursor.rowcount

# Usage
rows_deleted = delete_student(5)

# ============================================================
# MULTIPLE PARAMETERS
# ============================================================

def search_students(first_name, min_age, max_age):
    query = """
        SELECT * FROM students 
        WHERE first_name LIKE %s 
        AND age BETWEEN %s AND %s
    """
    cursor.execute(query, (f"%{first_name}%", min_age, max_age))
    return cursor.fetchall()

# Usage
results = search_students("Ra", 18, 25)

Key points for each operation:

  • SELECT — use %s in WHERE clause
  • INSERT — use %s for each value
  • UPDATE — use %s for SET values and WHERE
  • DELETE — use %s in WHERE clause
  • Always pass data as a tuple

Quick Check: What placeholder is used in parameterized queries with mysql-connector-python? (Answer: %s)

Real-World Example: Secure User System

5

Building a Secure User Authentication System

# ============================================================
# SECURE USER AUTHENTICATION SYSTEM
# ============================================================

import mysql.connector
import hashlib  # For password hashing

class SecureUserSystem:
    """A secure user system using parameterized queries"""
    
    def __init__(self, db_config):
        self.db_config = db_config
        self.connection = None
        self.cursor = None
    
    def connect(self):
        try:
            self.connection = mysql.connector.connect(**self.db_config)
            self.cursor = self.connection.cursor()
            return True
        except mysql.connector.Error as e:
            print(f"Connection failed: {e}")
            return False
    
    def hash_password(self, password):
        """Hash a password for secure storage"""
        return hashlib.sha256(password.encode()).hexdigest()
    
    def create_user(self, username, password, email):
        """Create a new user (SECURE)"""
        # Hash the password
        hashed_password = self.hash_password(password)
        
        # Parameterized query
        query = """
            INSERT INTO users (username, password_hash, email, created_at)
            VALUES (%s, %s, %s, NOW())
        """
        try:
            self.cursor.execute(query, (username, hashed_password, email))
            self.connection.commit()
            print(f" User '{username}' created successfully")
            return self.cursor.lastrowid
        except mysql.connector.IntegrityError:
            print(f" Username '{username}' already exists")
            return None
        except mysql.connector.Error as e:
            print(f" Error: {e}")
            self.connection.rollback()
            return None
    
    def login_user(self, username, password):
        """Authenticate a user (SECURE)"""
        hashed_password = self.hash_password(password)
        
        # Parameterized query
        query = """
            SELECT user_id, username, email, created_at
            FROM users
            WHERE username = %s AND password_hash = %s
        """
        self.cursor.execute(query, (username, hashed_password))
        user = self.cursor.fetchone()
        
        if user:
            print(f" Welcome back, {username}!")
            return user
        else:
            print(f" Invalid username or password")
            return None
    
    def update_user_email(self, user_id, new_email):
        """Update user email (SECURE)"""
        query = "UPDATE users SET email = %s WHERE user_id = %s"
        self.cursor.execute(query, (new_email, user_id))
        self.connection.commit()
        return self.cursor.rowcount
    
    def delete_user(self, user_id):
        """Delete a user (SECURE)"""
        query = "DELETE FROM users WHERE user_id = %s"
        self.cursor.execute(query, (user_id,))
        self.connection.commit()
        return self.cursor.rowcount
    
    def search_users(self, search_term):
        """Search for users (SECURE)"""
        query = """
            SELECT user_id, username, email
            FROM users
            WHERE username LIKE %s OR email LIKE %s
        """
        search_pattern = f"%{search_term}%"
        self.cursor.execute(query, (search_pattern, search_pattern))
        return self.cursor.fetchall()
    
    def close(self):
        if self.cursor:
            self.cursor.close()
        if self.connection:
            self.connection.close()

# ============================================================
# DEMONSTRATION
# ============================================================

db_config = {
    "host": "localhost",
    "user": "root",
    "password": "secret",
    "database": "myapp_db"
}

# Create the users table first (if not exists)
# CREATE TABLE IF NOT EXISTS users (
#     user_id INT AUTO_INCREMENT PRIMARY KEY,
#     username VARCHAR(50) UNIQUE NOT NULL,
#     password_hash VARCHAR(255) NOT NULL,
#     email VARCHAR(100) UNIQUE NOT NULL,
#     created_at DATETIME DEFAULT CURRENT_TIMESTAMP
# )

system = SecureUserSystem(db_config)
if system.connect():
    
    # 1. Create users
    print("\n Creating users...")
    system.create_user("rahul_sharma", "password123", "rahul@email.com")
    system.create_user("priya_patel", "secure456", "priya@email.com")
    
    # 2. Login
    print("\n Testing login...")
    system.login_user("rahul_sharma", "password123")
    system.login_user("rahul_sharma", "wrongpassword")
    
    # 3. Search users
    print("\nšŸ” Searching for users...")
    results = system.search_users("rahul")
    for user in results:
        print(f"  Found: {user[1]} ({user[2]})")
    
    # 4. Update email
    print("\n Updating email...")
    rows = system.update_user_email(1, "rahul_new@email.com")
    print(f"Updated {rows} user(s)")
    
    system.close()

This secure example shows:

  • Password hashing for security
  • Parameterized queries for all operations
  • Proper error handling
  • Login authentication
  • User search with LIKE
  • Update and delete operations

Quick Check: Why is password hashing important? (Answer: It protects passwords even if the database is compromised)

Best Practices

6

Keeping Your Database Safe

# ============================================================
# BEST PRACTICES FOR PARAMETERIZED QUERIES
# ============================================================

print("1. ALWAYS USE PARAMETERIZED QUERIES")
print("   - Never use string concatenation for SQL")
print("   - Never use f-strings for SQL")
print("   - Always use %s placeholders")

print("\n2. USE PARAMETERIZED QUERIES EVERYWHERE")
print("   - SELECT queries with user input")
print("   - INSERT queries")
print("   - UPDATE queries")
print("   - DELETE queries")

print("\n3. NEVER TRUST USER INPUT")
print("   - Always treat user input as potentially dangerous")
print("   - Validate input even with parameterized queries")

print("\n4. USE THE LEAST PRIVILEGE PRINCIPLE")
print("   - Database user should have minimal permissions")
print("   - Don't use root/admin for application")

print("\n5. HASH PASSWORDS")
print("   - Never store passwords in plain text")
print("   - Use strong hashing (SHA-256, bcrypt)")

print("\n6. USE ENVIRONMENT VARIABLES")
print("   - Don't hardcode credentials")
print("   - Store them securely")

print("\n7. LOG SUSPICIOUS ACTIVITY")
print("   - Monitor for SQL injection attempts")
print("   - Log errors for debugging")

print("\n8. KEEP YOUR DRIVERS UPDATED")
print("   - Update mysql-connector-python regularly")
print("   - Security patches are important")

Summary of best practices:

  • Always use parameterized queries — never string concatenation
  • Never trust user input — treat everything as unsafe
  • Hash passwords — never store in plain text
  • Use environment variables — for credentials
  • Log suspicious activity — monitor for attacks

Quick Check: What is the most important rule for database security? (Answer: Always use parameterized queries and never trust user input)

Try It Yourself

Experiment with parameterized queries in the editor below.

Loading Pyodide... 0%
Python Code Editor
========================================
PARAMETERIZED QUERIES - PRACTICE
========================================

1. SELECT WITH PARAMETERS
----------------------------------------

šŸ” Finding students older than 23...
Found 4 students:
Priya Patel - Age: 25
Amit Singh - Age: 24
Vikram Kumar - Age: 26
Ravi Desai - Age: 27

šŸ” Finding students named 'Amit'...
Found 1 students:
Amit Singh - Age: 24

2. INSERT WITH PARAMETERS
----------------------------------------

Before insert:
-------------------------------------------------------
ID: 1 | Rahul Sharma | Age: 22 | rahul@email.com
ID: 2 | Priya Patel | Age: 25 | priya@email.com
ID: 3 | Amit Singh | Age: 24 | amit@email.com
ID: 4 | Sneha Reddy | Age: 23 | sneha@email.com
ID: 5 | Vikram Kumar | Age: 26 | vikram@email.com
ID: 6 | Anjali Nair | Age: 21 | anjali@email.com
ID: 7 | Ravi Desai | Age: 27 | ravi@email.com
ID: 8 | Meera Iyer | Age: 23 | meera@email.com
Total: 8 students

āœļø Inserting new student...
Inserted student with ID: 9

After insert:
-------------------------------------------------------
ID: 1 | Rahul Sharma | Age: 22 | rahul@email.com
ID: 2 | Priya Patel | Age: 25 | priya@email.com
ID: 3 | Amit Singh | Age: 24 | amit@email.com
ID: 4 | Sneha Reddy | Age: 23 | sneha@email.com
ID: 5 | Vikram Kumar | Age: 26 | vikram@email.com
ID: 6 | Anjali Nair | Age: 21 | anjali@email.com
ID: 7 | Ravi Desai | Age: 27 | ravi@email.com
ID: 8 | Meera Iyer | Age: 23 | meera@email.com
ID: 9 | Test User | Age: 30 | test@email.com
Total: 9 students

3. UPDATE WITH PARAMETERS
----------------------------------------

āœļø Updating student ID 1 age to 24...
Updated 1 student(s)

After update:
-------------------------------------------------------
ID: 1 | Rahul Sharma | Age: 24 | rahul@email.com
ID: 2 | Priya Patel | Age: 25 | priya@email.com
ID: 3 | Amit Singh | Age: 24 | amit@email.com
ID: 4 | Sneha Reddy | Age: 23 | sneha@email.com
ID: 5 | Vikram Kumar | Age: 26 | vikram@email.com
ID: 6 | Anjali Nair | Age: 21 | anjali@email.com
ID: 7 | Ravi Desai | Age: 27 | ravi@email.com
ID: 8 | Meera Iyer | Age: 23 | meera@email.com
ID: 9 | Test User | Age: 30 | test@email.com
Total: 9 students

4. DELETE WITH PARAMETERS
----------------------------------------

šŸ—‘ļø Deleting student ID 8...
Deleted 1 student(s)

After delete:
-------------------------------------------------------
ID: 1 | Rahul Sharma | Age: 24 | rahul@email.com
ID: 2 | Priya Patel | Age: 25 | priya@email.com
ID: 3 | Amit Singh | Age: 24 | amit@email.com
ID: 4 | Sneha Reddy | Age: 23 | sneha@email.com
ID: 5 | Vikram Kumar | Age: 26 | vikram@email.com
ID: 6 | Anjali Nair | Age: 21 | anjali@email.com
ID: 7 | Ravi Desai | Age: 27 | ravi@email.com
ID: 9 | Test User | Age: 30 | test@email.com
Total: 8 students

Parameterized queries keep your database secure!

You've Got It!

You now understand how to use parameterized queries to keep your database safe. You know what SQL injection is and how to prevent it.

Quick Quiz

Test what you've learned:

1. What is a parameterized query?
2. What is SQL injection?
3. How do you write a parameterized query in Python with mysql-connector?
4. What happens if you use string concatenation for SQL?
5. What is the #1 way to prevent SQL injection?

Frequently Asked Questions

What is the difference between %s and ? in parameterized queries? ā–¼

%s is used with mysql-connector-python. ? is used with other Python database libraries like sqlite3. The concept is the same — they're both placeholders for data.

Can I use parameterized queries with LIKE? ā–¼

Yes! You can use parameterized queries with LIKE. Just include the % wildcard in the data, like this: cursor.execute("SELECT * FROM users WHERE name LIKE %s", (f"%{search_term}%",))

Do parameterized queries affect performance? ā–¼

No, parameterized queries actually improve performance for repeated queries because the database can cache the query plan. They're both faster AND more secure.

What is a common interview question about parameterized queries? ā–¼

Common questions include: "What is SQL injection and how do you prevent it?" "Explain how parameterized queries work" and "Why is it unsafe to use string concatenation for SQL queries?"

Can I use parameterized queries with column names? ā–¼

No, parameterized queries only work for values, not for column or table names. For dynamic column names, you need to validate the input against a whitelist of allowed column names.

Where to Go From Here

Now that you know how to keep your database secure with parameterized queries, check out these related topics:

Transactions

Learn how to safely manage multiple database operations.

Learn More →

Error Handling

Learn how to handle database errors properly.

Learn More →

Connection Pooling

Learn how to manage database connections efficiently.

Learn More →
Interview Resources
  • Python Syntax & Variables Interview Questions
  • Top SQL Interview Questions & Answers
  • SQL Joins: Displaying Data from Multiple Tables FAQ
  • Python Lists and Dictionaries Interview Questions
  • Python OOP Interview Questions
  • SQL Set Operators Interview Questions
Previous: Delete Data Next: Transactions →