Sling Academy
Home/Kotlin/Kotlin: Using SQL Queries with Placeholders in SQLite

Kotlin: Using SQL Queries with Placeholders in SQLite

Last updated: December 05, 2024

SQLite is a software library that provides a relational database management system. It's an ideal choice for mobile app developers who aim to store data locally on Android devices. Kotlin, being the modern, statically typed programming language, makes it easier to handle these operations with its concise syntax and rich features.

In this article, we’ll dive deep into using SQL queries with placeholders in SQLite, which not only helps in making data manipulation safe but also enhances readability and maintainability of code.

Setting Up SQLite in Kotlin

Before we start executing SQL queries with placeholders, we need to incorporate SQLite in our Kotlin Android application. Let's begin by adding the necessary dependencies to your app-level build.gradle file:


dependencies {
    implementation "androidx.sqlite:sqlite:2.2.0"
    implementation "androidx.sqlite:sqlite-framework:2.2.0"
}

Sync the project to ensure all dependencies are properly added. Now, we’re ready to make use of SQLite functionality in our Kotlin project!

Creating a Database

First, we need to create a database instance that we can interact with. The following Kotlin code snippet shows how to create a subclass of SQLiteOpenHelper:


import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper

class DatabaseHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {

    override fun onCreate(db: SQLiteDatabase?) {
        val createTableSQL = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER)"
        db?.execSQL(createTableSQL)
    }

    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
        db?.execSQL("DROP TABLE IF EXISTS users")
        onCreate(db)
    }

    companion object {
        const val DATABASE_NAME = "users.db"
        const val DATABASE_VERSION = 1
    }
}

With this setup, our database will be able to store and manage user records efficiently.

Using SQL Queries with Placeholders

Using placeholders in SQL queries makes our application safer and less susceptible to SQL injection attacks. Instead of directly inserting values into SQL statements, we'll utilize the SQL syntax for placeholders along with methods that bind values to these placeholders.

Here's an example of how to use placeholders in an SQLite insert operation:


fun insertUser(name: String, age: Int) {
    val db = writableDatabase
    val sql = "INSERT INTO users (name, age) VALUES (?, ?)"
    val statement = db.compileStatement(sql)
    statement.bindString(1, name)
    statement.bindLong(2, age.toLong())
    statement.executeInsert()
    db.close()
}

The question marks (?) in the SQL string are placeholders, which are replaced by the actual values through the bindString and bindLong methods of the compiled statement.

Retrieving Data

Placeholders can similarly be used for retrieving data, which is particularly useful when querying dynamic data sets. Here is how you can use placeholders in a select query:


fun getUserByName(name: String): User? {
    val db = readableDatabase
    val sql = "SELECT * FROM users WHERE name = ?"
    val cursor = db.rawQuery(sql, arrayOf(name))

    var user: User? = null
    if (cursor.moveToFirst()) {
        user = User(
            cursor.getInt(cursor.getColumnIndexOrThrow("id")),
            cursor.getString(cursor.getColumnIndexOrThrow("name")),
            cursor.getInt(cursor.getColumnIndexOrThrow("age"))
        )
    }
    cursor.close()
    db.close()
    return user
}

This example fetches a user from the database based on their name using the placeholder technique.

Benefits of Using Placeholders

  • Security: As mentioned, placeholders prevent SQL injection attacks, making databases more secure.
  • Readability: Placeholders help in understanding the dependencies and dynamically involved data in SQL statements.
  • Efficiency: Using placeholders and compiled statements can potentially be more efficient as it allows SQLite to cache compiled queries.

Conclusion

Incorporating placeholders when working with SQL in SQLite databases from Kotlin improves both the security and performance of the interaction with the database. With the code snippets provided, you can now start implementing SQL operations using placeholders in your Kotlin Android apps.

Next Article: How to Handle SQLite Exceptions in Kotlin

Previous Article: Working with SQLite Transactions in Kotlin

Series: Kotlin - Interacting with Databases

Kotlin

You May Also Like

  • How to Use Modulo for Cyclic Arithmetic in Kotlin
  • Kotlin: Infinite Loop Detected in Code
  • Fixing Kotlin Error: Index Out of Bounds in List Access
  • Setting Up JDBC in a Kotlin Application
  • Creating a File Explorer App with Kotlin
  • How to Work with APIs in Kotlin
  • What is the `when` Expression in Kotlin?
  • Writing a Script to Rename Multiple Files Programmatically in Kotlin
  • Using Safe Calls (`?.`) to Avoid NullPointerExceptions in Kotlin
  • Chaining Safe Calls for Complex Operations in Kotlin
  • Using the Elvis Operator for Default Values in Kotlin
  • Combining Safe Calls and the Elvis Operator in Kotlin
  • When to Avoid the Null Assertion Operator (`!!`) in Kotlin
  • How to Check for Null Values with `if` Statements in Kotlin
  • Using `let` with Nullable Variables for Scoped Operations in Kotlin
  • Kotlin: How to Handle Nulls in Function Parameters
  • Returning Nullable Values from Functions in Kotlin
  • Safely Accessing Properties of Nullable Objects in Kotlin
  • How to Use `is` for Nullable Type Checking in Kotlin