Параметрированный запрос И проверка ввода - это путь. Существует множество сценариев, в которых может произойти SQL-инъекция, хотя используется mysql_real_escape_string()
.
Эти примеры уязвимы для SQL-инъекции:
$offset = isset($_GET['o']) ? $_GET['o'] : 0;
$offset = mysql_real_escape_string($offset);
RunQuery("SELECT userid, username FROM sql_injection_test LIMIT $offset, 10");
или
$order = isset($_GET['o']) ? $_GET['o'] : 'userid';
$order = mysql_real_escape_string($order);
RunQuery("SELECT userid, username FROM sql_injection_test ORDER BY `$order`");
В обоих случаях вы не можете использовать '
для защиты инкапсуляции.
Источник : Непредвиденная инъекция SQL (при эвакуации Недостаточно)
bool exists;
try
{
// ANSI SQL way. Works in PostgreSQL, MSSQL, MySQL.
var cmd = new OdbcCommand(
"select case when exists((select * from information_schema.tables where table_name = '" + tableName + "')) then 1 else 0 end");
exists = (int)cmd.ExecuteScalar() == 1;
}
catch
{
try
{
// Other RDBMS. Graceful degradation
exists = true;
var cmdOthers = new OdbcCommand("select 1 from " + tableName + " where 1 = 0");
cmdOthers.ExecuteNonQuery();
}
catch
{
exists = false;
}
}
Я не думаю, что там существует один универсальный путь, который работает на все Базы данных, так как это - что-то очень определенное, которое зависит от того, как DB создается.
, Но, почему Вы хотите сделать это использование определенного запроса? Разве Вы не можете абстрагировать реализацию далеко от того, что Вы хотите сделать? Я имею в виду: почему бы не создать универсальный интерфейс, который имеет среди других, метод, названный 'TableExists (представляют имя таблицы в виде строки)', например. Затем для каждого DBMS, который Вы хотите поддерживать, Вы создаете класс, который реализует этот интерфейс, и в методе TableExists, Вы пишете определенную логику для этого DBMS.
реализация SQLServer будет тогда содержать запрос, который запрашивает sysobjects.
В Вашем приложении, у Вас может быть класс фабрики, который создает корректную реализацию для данного контекста, и затем Вы просто называете метод TableExists.
, Например:
IMyInterface foo = MyFactory.CreateMyInterface (SupportedDbms.SqlServer);
if( foo.TableExists ("mytable") )
...
я думаю, что это - то, как я должен сделать это.
Если Вы пробуете за независимость базы данных, необходимо будет принять минимальный стандарт. IIRC представления ANSI INFORMATION_SCHEMA требуются для соответствия ODBC, таким образом, Вы могли запросить против них как:
select count (*)
from information_schema.tables
where table_name = 'foobar'
, Учитывая, что Вы используете ODBC, можно также использовать различный вызовы API ODBC для получения этих метаданных также.
Принимают во внимание, что мобильность приравнивается к неперезаписываемый тест где угодно , таким образом, Вы все еще оказываетесь перед необходимостью тестировать приложение на каждой платформе, которую Вы намереваетесь поддерживать. Это означает, что Вы по сути ограничены конечным числом возможных платформ базы данных, поскольку у Вас только есть так много ресурса для тестирования.
результат - то, что необходимо найти наименьший общий знаменатель для приложения (который довольно много более тверд, чем оно ищет SQL), или создайте зависимый от платформы раздел, где непортативные функции могут быть включены на основе на платформу.
Я полностью поддерживаю ответ Frederik Gheysels. Если необходимо поддерживать несколько систем баз данных, необходимо реализовать код против абстрактного интерфейса с определенными реализациями система для каждой базы данных. Существует намного больше примеров несовместимого синтаксиса, чем просто проверка существующую таблицу (например: ограничение запроса к определенному числу строк).
, Но если действительно необходимо выполнить проверку с помощью обработки исключений от примера, необходимо использовать следующий запрос, который более эффективен, чем КОЛИЧЕСТВО (*), потому что база данных не имеет никакой фактической работы выбора, чтобы сделать:
SELECT 1 FROM my_table WHERE 1=2
Я постарался бы не выполняться select count(x) from xxxxxx
, поскольку DBMS будет на самом деле идти вперед и делать это, который может занять время для большой таблицы.
Вместо этого всего готовятся select * from mysterytable
запрос. Готовить перестанет работать, если mysterytable не существует. Нет никакой потребности на самом деле выполнить подготовленный оператор.
В текущем проекте на моем задании я должен записать 'агент данных', который поддерживал бы много типов БД.
, Таким образом, я решил сделать затем: запишите базовый класс с основой (независимая база данных) функциональность с помощью виртуальных методов и переопределения в подклассах все определенные для базы данных моменты