You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否使用Go SQL库对CREATE语句进行参数化?

Can you parameterize CREATE TABLE statements with Go's SQL library?

Short answer: No, Go's standard database/sql library doesn't support parameterizing identifiers like table names, column names, or data types in DDL statements (like CREATE TABLE). Parameterization only works for values in DML statements (SELECT/INSERT/UPDATE/DELETE), not for structural parts of the SQL syntax.

Why is that?

Parameterization works by separating the SQL template from the data: the database pre-compiles the fixed SQL structure, and parameters are passed as raw data that never gets parsed as SQL syntax. But table/column names and data types are part of the SQL's structural definition—databases can't pre-compile a template where the core structure (like which table to create) is variable. Using parameter placeholders for these parts would treat them as string values (e.g., turning CREATE TABLE ? into CREATE TABLE 'users'), which is invalid SQL because identifiers aren't wrapped in quotes.

Safe alternatives to string concatenation

Since you can't use parameterization here, you need to mitigate SQL injection risks with strict input validation:

  • Whitelist allowed values: Restrict users to selecting from pre-approved table names, column names, and data types. This is the most secure approach because it eliminates untrusted input entirely.
  • Strict input sanitization + identifier escaping: If you must accept custom inputs, first validate that identifiers only contain safe characters (letters, numbers, underscores), then wrap them in the appropriate database-specific escape characters (backticks for MySQL, double quotes for PostgreSQL, square brackets for SQL Server).

Example: Whitelist-based table creation

import (
    "database/sql"
    "fmt"
    "regexp"
    "strings"
)

// Predefine safe, allowed values
var allowedTables = map[string]bool{
    "users":    true,
    "products": true,
}

var allowedColumnTypes = map[string]bool{
    "INT":          true,
    "VARCHAR(100)": true,
    "DATE":         true,
}

func CreateTable(db *sql.DB, tableName string, columns map[string]string) error {
    // Validate table name against whitelist
    if !allowedTables[tableName] {
        return fmt.Errorf("invalid or disallowed table name: %s", tableName)
    }

    // Validate each column
    columnDefs := make([]string, 0, len(columns))
    for colName, colType := range columns {
        // Ensure column name only contains safe characters
        if !regexp.MustCompile(`^[a-zA-Z0-9_]+$`).MatchString(colName) {
            return fmt.Errorf("invalid column name: %s (only letters, numbers, underscores allowed)", colName)
        }
        // Validate column type against whitelist
        if !allowedColumnTypes[colType] {
            return fmt.Errorf("invalid type for column %s: %s", colName, colType)
        }
        // Escape column name for MySQL (adjust for your DB)
        columnDefs = append(columnDefs, fmt.Sprintf("`%s` %s", colName, colType))
    }

    // Build the final CREATE statement
    createQuery := fmt.Sprintf(
        "CREATE TABLE IF NOT EXISTS `%s` (%s)",
        tableName,
        strings.Join(columnDefs, ", "),
    )

    _, err := db.Exec(createQuery)
    return err
}

This approach ensures that only safe, pre-approved inputs make their way into your DDL statements, eliminating SQL injection risks without relying on parameterization.

内容的提问来源于stack exchange,提问作者thisischuck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:35:13