Используете заполнитель? в запросе Go mySql для чего-либо, кроме int

0

Я уже установил и установил соединение с базой данных mysql. Он работает, и я могу возвращать строки, используя как db.Query, так и сначала создавая запрос. Я могу использовать местозаполнитель? затем указать идентификатор. Можно ли использовать? в качестве заполнителя для имени столбца? В примере здесь я пытаюсь вернуть все строки из столбца firstName в персонах таблицы.

qry, err := db.Prepare("SELECT ? FROM persons")
if err != nil { log.Fatal(err) }
defer qry.Close()
rows, err :=qry.Query("firstName")
if err != nil { log.Fatal(err) }
defer rows.Close()

Я получаю следующую ошибку: Ошибка 1064: У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с?? в строке 1

  • 0
    Заполнители предназначены только для данных, их нельзя использовать для идентификаторов (имен таблиц, столбцов и т. Д.). Если вы чувствуете, что вам нужно сделать это, вы, скорее всего, делаете это неправильно.
  • 0
    @ Питер Я просто тестировал пакет и думал, что создам очень простой запрос, который можно расширить с помощью заполнителей, чтобы более эффективно тестировать несколько сценариев. Учитывая, что решения Prepare () и Query () предназначены для защиты от инъекций, это ограничение имеет смысл.
Теги:
go

1 ответ

2
Лучший ответ

Вы не можете использовать заполнители для идентификаторов (например, имена таблиц и столбцов), заполнители для значений. Вы можете думать, что идентификаторы похожи на имена переменных или функций в Go, поэтому возможность использования заполнителей для идентификаторов будет сродни тому, чтобы иметь eval как на разных языках сценариев.

Это сводит вас к использованию fmt.Sprintf и подобных строковых операций для построения SQL, когда вы не знаете идентификаторы до выполнения:

col := "firstName"
sql := fmt.Sprintf("select %s from persons", col)

но это открывает вам проблемы с SQL-инъекциями и цитированием, поэтому вам нужен какой-то белый список:

quotedColumns := map[string]string{
    "firstName": "'firstName'",
    "lastName": "'lastName'",
    ...
}

quoted, ok := quotedColumns[columnName]
if !ok {
    // Do something with the error here and run away...
}
sql := fmt.Sprintf("select %s from persons", quoted)

Обратите внимание, что я включил обратную ссылку MySQL в значениях карты. Там нет ничего в стандартном интерфейсе для цитирования/экранирования идентификатора, поэтому вам нужно сделать это самостоятельно. Если вы уже пишете карту белого списка вручную, вы можете также включить цитирование вручную; в противном случае вы могли бы написать свою собственную функцию кавычек для идентификаторов, прочитав документацию MySQL по цитированию и выполнению простых (простых) операций с строкой.

  • 0
    Я понял, что это так, поскольку я смог использовать Exec () для вставки строк в строку SQL с помощью VALUES (?), Но не для изменения идентификаторов. Sprintf () - интересный конец обхода ограничения, о котором я не думал.
  • 1
    @spynovel, позаботьтесь о том, чтобы сшивать только строковые константы вместе со спринтами. Оттуда легко перейти к тому, чтобы больше не использовать параметры.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню