Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Валидирунг SQL-строк


Автор: Pankon 11.10.2006, 11:43
Можно ли узнать, что систаксис SQL-строки "правильный"?


Автор: sergejzr 11.10.2006, 12:07
При компиляции - нет. Ведь строка может создаваться динамически в процессе выполнения программы. 
Единственный сбособ - распечатывать ошибку БД при выполнении запроса.

ПС:
По-русски это называется "валидация" smile

Автор: Pankon 11.10.2006, 12:22
Цитата(sergejzr @  11.10.2006,  12:07 Найти цитируемый пост)
строка может создаваться динамически
 вот такую строку и надо проверить

Цитата(sergejzr @  11.10.2006,  12:07 Найти цитируемый пост)
ошибку БД при выполнении запроса
 а это-то и хотелось избежать

Неужели нет способа...

ПС. Писать синтаксический анализатор SQL-строки - не предлогать...

Автор: ivashkanet 11.10.2006, 12:27
Pankon, так у VS вроде есть SQL анализатор  smile 
Вернее не анализатор, а SQL-builder вот в нем и проверь свою строку

Автор: sergejzr 11.10.2006, 12:30
Цитата(Pankon @  11.10.2006,  11:22 Найти цитируемый пост)
ПС. Писать синтаксический анализатор SQL-строки - не предлогать... 

Зачем его писать, когда БД это делает.

Полюбому точно отвалидировать запрос может только сама БД. Их миллион разных и программно этого сделать невозможно (да и не надо в большинстве случаев.)
В мускуле например можно приписывать вначале запроса "EXPLAIN" тогда запрос выполняться не будет, но сообщение об ошибке(если таковая имеется) выдаст.
Но это всё уже при выполнении программы.
Вообще, если запрос один раз хорошо отлажен, проверять его каждый раз не имеет смысла.



Автор: Pankon 11.10.2006, 12:39
Цитата(ivashkanet @  11.10.2006,  12:27 Найти цитируемый пост)
SQL-builder вот в нем и проверь свою строку 
Цитата(sergejzr @  11.10.2006,  12:30 Найти цитируемый пост)
Вообще, если запрос один раз хорошо отлажен, проверять его каждый раз не имеет смысла.
 строка генерируется программно, некоторые ее части зависят от того, что набрал пользователь... а некоторые, от того, что пользователь ввел...



Цитата(sergejzr @  11.10.2006,  12:30 Найти цитируемый пост)
и не надо в большинстве случаев
 это как раз тот случай, когда надо... Динамически сгенерированные строки передаются на несколько серверов, где и происходит коннект с базой данных, и если строки пошли "неправильные", то получать 10 сообшений (с каждого сервера) об неправильном SQL не хотелось бы...

Автор: ivashkanet 11.10.2006, 12:43
Цитата(Pankon @  11.10.2006,  12:39 Найти цитируемый пост)
Динамически сгенерированные строки передаются на несколько серверов, где и происходит коннект с базой данных, и если строки пошли "неправильные", то получать 10 сообшений (с каждого сервера) об неправильном SQL не хотелось бы...

Ну так заведи тестовую таблицу и к ней обращайся ловя (или нет) по пути эксепшены. 
Или ты дебажить проект будешь на реальных серверах?

Автор: Pankon 11.10.2006, 12:55
Цитата(ivashkanet @  11.10.2006,  12:43 Найти цитируемый пост)
тестовую таблицу
 или тестовую базу данных... smile 

Цитата(ivashkanet @  11.10.2006,  12:43 Найти цитируемый пост)
Или ты дебажить проект будешь на реальных серверах? 
Приложение уже работает, только время от времени дает сбои(сообшения об ошибке на каждом сервере), по причине неверного ввода пользователями динамических частей SQL-строки

Автор: sergejzr 11.10.2006, 12:56
Цитата(Pankon @  11.10.2006,  11:39 Найти цитируемый пост)
строка генерируется программно, некоторые ее части зависят от того, что набрал пользователь... а некоторые, от того, что пользователь ввел...

Это в 99,99% приложений так. Программно надо проверять отдельные части, чтобы не послать строку туда, где необходимо целое число, экранировать кавычки, итд.
В отлаженных запросах ошибки могут быть только логические но не синтактические!

Автор: ivashkanet 11.10.2006, 13:01
Цитата(Pankon @  11.10.2006,  12:55 Найти цитируемый пост)
или тестовую базу данных... 

Есть много вариантов:
1) Тестовая таблица в реальной БД на реальном сервере
2) Тестовая таблица в тестовой БД на реальном сервере
3) Тестовая таблица в реальной БД на тестовом сервере
4) Тестовая таблица в тестовой БД на тестовом сервере
Какой выбираешь?
Цитата(Pankon @  11.10.2006,  12:55 Найти цитируемый пост)
неверного ввода пользователями динамических частей SQL-строки

Пользователи сами вводят SQL-строки  smile Приложение для программистов?  smile 

Цитата(Pankon @  11.10.2006,  12:55 Найти цитируемый пост)
Приложение уже работает, только время от времени дает сбои(сообшения об ошибке на каждом сервере), по причине неверного ввода пользователями динамических частей SQL-строки

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

Добавлено @ 13:07 
Цитата(ivashkanet @  11.10.2006,  13:01 Найти цитируемый пост)
3) Тестовая таблица в реальной БД на тестовом сервере

Третий не катит  smile 

Автор: Дрон 11.10.2006, 13:10
Цитата(ivashkanet @  11.10.2006,  14:01 Найти цитируемый пост)
ользователи сами вводят SQL-строки  smile Приложение для программистов?  smile 

Во-во. Сам удивляюсь smile

Pankon, ты уж поаккуратней с "динамическими частями SQL-строки". А то мало ли у тебя там запросы вроде:
Код
string sql = string.Format("SELECT * FROM users WHERE login = '{0}' AND password = '{1}'", login, password);

Если так, то тут никакая проверка синтаксиса уже не поможет, ведь если я введу в качестве логина вот такое:
Код
'; TRUNCATE TABLE users; --

то синтаксис останется верным, а результат...  smile 

Автор: Pankon 11.10.2006, 13:19
Цитата(ivashkanet @  11.10.2006,  13:01 Найти цитируемый пост)
Тестовая таблица
Цитата(ivashkanet @  11.10.2006,  13:01 Найти цитируемый пост)
Какой выбираешь?
в запросе несколько таблиц... (можно сказать - почти вся база)


Цитата(ivashkanet @  11.10.2006,  13:01 Найти цитируемый пост)
Приложение для программистов?
 некоторых можно так назвать


Цитата(sergejzr @  11.10.2006,  12:56 Найти цитируемый пост)
В отлаженных запросах
Цитата(ivashkanet @  11.10.2006,  13:01 Найти цитируемый пост)
оттестируй новый запрос
 все запросы, которые вводят пользователи из группы "так называемые Администраторы" предусмотреть невозможно, а им по определению(читай - техническое задание) должна быть доступна часть строки для динамического ввода... Большой процент ошибок, что вводят пользователи, такого характера  - "AND T1.F1=10 AND T2.F2=20 AND T3.F1=<30" smile Поэтому возник http://forum.vingrad.ru/index.php?showtopic=115950&view=findpost&p=884816 такой вопрос

Добавлено @ 13:21 
Цитата(Дрон @  11.10.2006,  13:10 Найти цитируемый пост)
ты уж поаккуратней
 техническое задание не изменить...

Автор: ivashkanet 11.10.2006, 13:25
Цитата(Pankon @  11.10.2006,  13:19 Найти цитируемый пост)
в запросе несколько таблиц... (можно сказать - почти вся база)

Ааа, да, тута я тормазнул  smile 
Цитата(Pankon @  11.10.2006,  13:19 Найти цитируемый пост)
Большой процент ошибок, что вводят пользователи, такого характера  - "AND T1.F1=10 AND T2.F2=20 AND T3.F1=<30"... Поэтому возник тут  такой вопрос

Так предложи сделать "query builder", типа несколько выпадающих списков, как в Экселе, например, 

Первый список: "поле", второй: ">,<,<=,>=", третий: "значение".

P.S. Так проблемма в этом: "=<"? Взашей таких "админов" надо  smile 

Автор: Pankon 11.10.2006, 13:32
Цитата(ivashkanet @  11.10.2006,  13:25 Найти цитируемый пост)
сделать "query builder"
 эта идея у меня давно витает... но не для этого проекта...

Цитата(ivashkanet @  11.10.2006,  13:25 Найти цитируемый пост)
Взашей таких "админов"
 это "так называемые Администраторы" не компьютерных систем smile, а портала...

Добавлено @ 13:33 
Цитата(ivashkanet @  11.10.2006,  13:25 Найти цитируемый пост)
несколько выпадающих списков
 точнее сказать "несколько десятков"  smile 

Автор: Дрон 11.10.2006, 14:20
Задача:
- проверить синтаксис SQL запроса, не выполняя его

Решение:
- нужно попытаться создать хранимую процедуру, содержащую предполагаемый запрос: при создании хранимой процедуры сервер проверит валидность её содержимого

Вот smile

ЗЫ: Кстати, а почему тема не в разделе про базы данных?

Автор: ivashkanet 11.10.2006, 14:28
Цитата(Дрон @  11.10.2006,  14:20 Найти цитируемый пост)
- нужно попытаться создать хранимую процедуру, содержащую предполагаемый запрос: при создании хранимой процедуры сервер проверит валидность её содержимого

А не накладно это будет? Ведь такие процедуры будут создаваться часто  smile 

Автор: Дрон 11.10.2006, 14:30
ivashkanet, дык-ть как я понял проверка синтаксиса нужна не перед выполнением: непосредственно перед выполнением она вообще бессмысленна, т.к. все ошибки будут выявлены сразу.

Проверка нужна один раз -- в момент ввода запроса пользователем, чтобы сразу же сказать, что он туда какую-то ерунду ввёл.

Автор: Pankon 11.10.2006, 14:30
Цитата(Дрон @  11.10.2006,  14:20 Найти цитируемый пост)
Кстати, а почему тема не в разделе про базы данных?
 Программирование-то под дот.нет...., где во FrameWork столько (без)дельных классов... Namespace System.Data например....

Цитата(Дрон @  11.10.2006,  14:20 Найти цитируемый пост)
попытаться создать хранимую процедуру
 а как? (имеется ввиду средствами дот.нет)

Добавлено @ 14:31 
Цитата(Дрон @  11.10.2006,  14:30 Найти цитируемый пост)
в момент ввода запроса пользователем
 ага

Автор: Дрон 11.10.2006, 14:43
Цитата(Pankon @  11.10.2006,  15:30 Найти цитируемый пост)
Программирование-то под дот.нет...., где во FrameWork столько (без)дельных классов... Namespace System.Data например....

Но ведь вопрос про базы данных, а не про .net в частности.

Цитата(Pankon @  11.10.2006,  15:30 Найти цитируемый пост)
а как? (имеется ввиду средствами дот.нет)

А какая у тебя БД?
И что значит средствами .NET? Работа с базой всегда идёт через SQL smile

Для MSSQL Server я бы сделал так:
Код

            string sqlToVerify = "DROP DATABASE master"; // будем проверять не выполняя (и не вздумай выполнять!!!) 

            using (SqlConnection conn = new SqlConnection("server=localhost;integrated security=SSPI"))
            {
                conn.Open();

                string spName = "SP_" + Guid.NewGuid().ToString("N"); // уникальное имя

                SqlCommand cmd = new SqlCommand();
                cmd.Connection = conn;
                try
                {
                    // попытаемся создать хр.пр.
                    cmd.CommandText = string.Format("CREATE PROCEDURE {0} AS {1};", spName, sqlToVerify);
                    cmd.ExecuteNonQuery();
                    
                    // если она нормально создалась, то надо её сразу и грохнуть :)
                    cmd.CommandText = string.Format("DROP PROCEDURE {0}", spName);
                    cmd.ExecuteNonQuery();
                }
                catch(SqlException ex)
                {
                    // значит синтаксис неверен 
                    MessageBox.Show(ex.Message);
                }
            }



Автор: sergejzr 11.10.2006, 14:52
Ну и для мускула smile 

Код

string sqlToVerify = "DROP DATABASE master"; // будем проверять не выполняя (и не вздумай выполнять!!!) 
            using (SqlConnection conn = new SqlConnection("server=localhost;user=root;password=0123456"))
            {
                conn.Open();
                string spName = "SP_" + Guid.NewGuid().ToString("N"); // уникальное имя
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = conn;
                try
                {
                    // попытаемся создать хр.пр.
                    cmd.CommandText = string.Format("EXPLAIN {0};",  sqlToVerify);
                    cmd.ExecuteNonQuery();
                }
                catch(SqlException ex)
                {
                    // значит синтаксис неверен 
                    MessageBox.Show(ex.Message);
                }
            }

Автор: Дрон 11.10.2006, 14:57
sergejzr, да, у них ещё проще -- только там будет не SqlConnection/SqlCommand, а свои классы с префиксом MySql smile

Для Oracle, кстати, тоже есть нечто подобное, только там чуть посложнее будет: просишь сервер посчитать план выполнения, и проверяешь посчитался ли он.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)