2014-10-15 4 views
4

Любая помощь здесь будет замечательной.Работа с параметрами Delphi XE7 Firedac

Я пытаюсь использовать параметры для динамического изменения «ORDER BY»

Ниже приведен код, я пытался, но, несмотря на следующий документации, которую я до сих пор получаю сообщение об ошибке «[FIREDAC] [Phys] [MYSQL] У вас есть ошибка в SQL синтаксисе ... рядом с "ORDER BY строки field" в строке 4'

Я поставил ParamCreate Истинных

Моей базы данных является MySQL

FDQuery1.Close; 
FDQuery1.SQL.Clear; 
FDQuery1.SQL.Add('SELECT *'); 
FDQuery1.SQL.Add('FROM my_table'); 
FDQuery1.SQL.Add('LIMIT 1000'); 
FDQuery1.SQL.Add(':id'); 
FDQuery1.ParamByName('id').AsString := 'ORDER BY some_field'; 
FDQuery1.Open; 
+0

предела последнего утверждение, а не заказ на – Passella

+2

Деталей может различаться для разных серверов SQL, но в качестве общего предложения, вещи вы можете параметризовать в инструкции SELECT, довольно ограничены. Обычно вы можете параметризовать значения столбцов, которые должны быть сопоставлены в предложении WHERE, но не f.i. имена столбцов и/или таблиц. Я точно не знаю о MySql, но из первых принципов я бы не ожидал, что будет возможно параметризовать предложение ORDER BY. Если вы используете набор данных на стороне клиента, вам может быть повезло определить индекс с требуемым порядком поиска на нем. – MartynA

+0

«Я бы не ожидал, что это будет возможно ...», потому что сервер не будет знать, когда запрос PREPAREd указывает, содержит ли предложение ORDER BY допустимые имена столбцов, а также не может оптимизатор запросов сервера сервера выполнять свою работу в неизвестное выражение/clause, которое может быть чем угодно, а не просто ORDER BY. – MartynA

ответ

8

Вы не указали сообщение об исключении, поскольку оно появляется. Вот сообщение оригинальный

[FireDAC] [Phys] [MySQL] У вас есть ошибка в вашем SQL синтаксиса ... рядом ''ORDER BY some_field'' в строке 4.

сравните с процитировать

[FIREDAC] [PHYS] [MYSQL] у вас есть ошибка в вашем SQL синтаксиса ... рядом "ORDER BY some_field" в строке 4


Чтобы избежать этого в будущем просто нажмите CTRL + C на сосредоточенного окна исключений и полное сообщение в буфер обмена и может быть вставлен где угодно


Теперь, прочитав это, ошибка теперь очень ясна.

Вы ожидаете получить заявление как этот

SELECT * 
FROM my_table 
LIMIT 1000 
ORDER BY some_field 

Но с помощью параметра вы получите следующее заявление

SELECT * 
FROM my_table 
LIMIT 1000 
'ORDER BY some_field' 

, и это именно то, что сообщение об исключении говорит вам.

Просто проверьте сообщение об исключении с предыдущим высказыванием

... рядом 'ORDER BY some_field' в строке 4.

и

... рядом ''ORDER BY some_field'' на линии 4.

В качестве вывода невозможно изменить сам оператор с использованием параметров. Вы можете передавать только значения в качестве параметров для оператора.

И правильное утверждение должно быть в любом случае

SELECT * 
FROM my_table 
ORDER BY some_field 
LIMIT 1000 
+0

Спасибо, имеет смысл. Я использовал Macro для этого представления ADO в Delphi 7, но это не представляется возможным в XE7 с использованием Firedac. Или я ошибаюсь? – Eishman

+0

Кстати, я пытаюсь использовать эти методы, потому что я не смог найти способ использовать «IndexFieldNames» для сортировки текстового поля с числами как числовое поле. MYSQL позволяет использовать «CAST» в вашем заказе. На самом деле это то, что я пытался сделать. – Eishman

+2

. Вы должны использовать параметры для лучшей производительности и ** для предотвращения [sql-injection] (http: //en.wikipedia. орг/вики/SQL_injection) **. Но это именно то, что вы пытаетесь сделать, введите sql-код с использованием параметров. –

1

RxLib имеет такую ​​функциональность. Он имеет MACRO opttions, где вы можете написать код так:

Выбор% fields_ от% table_ где% condition_ заказ на% order_

НО подмигнули только для использования qith BDE.

Будет замечательно, если кто-то перепишет код для работы с ADO ou FIREDAC.

3

вам нужен очень простой SQL-запрос:

FDQuery1.Close; 
FDQuery1.SQL.Text := 'SELECT * FROM my_table'; 
FDQuery1.Open; 

Чтобы установить предел количества записей, вы можете использовать свойство FDQuery1:

FDQuery1.FetchOptions.RecsMax := 1000; 

Для сортировки значений вы можете использовать

FDQuery1.IndexFieldNames = some_field 

вместо вашего кода.

+0

Это, безусловно, лучший ответ. Просто установите свойство FDQuery1.IndexFieldNames. Отлично сработано – DaveBoltman

2

Редактировать: О, я не ответил на ваш вопрос. Итак, для FireDac вы можете просто установить свойство FDQuery1.IndexFieldNames на имя поля/вы хотите заказать. Не нужно закрывать и повторно открывать запрос или изменять SQL.

Предыдущий ответ: Вы не можете передать код SQL [EDIT: в том числе ORDER BY и т.д.] в параметрах, только значения параметров, то есть целые числа, строки и т.д. Этот принцип является чрезвычайно важным, в противном случае вы могли бы пройти, например,

FDQuery1.ParamByName('id').AsString := '; TRUNCATE TABLE my_table'; 

Выполнение запроса затем удалит все в таблице, а не выполняет то, что он должен делать. Или с немного большей работой, ваш же запрос может возвращать пароли, номера кредитных карт или все остальное в вашей базе данных. Это было бы огромной уязвимостью и известно как SQL Injection. Пожалуйста, смотрите, например:

http://www.w3schools.com/sql/sql_injection.asp

http://sqlmap.org/

http://hackaday.com/2014/09/01/gaining-access-to-the-oculus-developer-database

7

Не знаю, если это помогает. Но вы можете использовать свойство «Макросы» TFDQuery, например Параметр, идентифицируемый символом «:», макросы идентифицируются как «!», Вы также можете комбинировать макросы и пары. Свойство Macros работает почти как свойство Params. Используйте TFDQuery.MacroByname для назначения значения макроса и используйте TFDQuery.MacroByname ('MacroName'). AsRaw назначит строку As-Is.

Таким образом, ваш запрос должен выглядеть следующим образом:

FDQuery1.Close; 
FDQuery1.SQL.Text := 'SELECT * FROM !TABLE_NAME !WHERE_CLAUSE !ORDERBY_CLAUSE'; 

FDQuery.MacroByname('Table_name').AsRaw := 'my_table'; 
FDQuery.MacroByname('Where_clause').AsRaw := 'WHERE field1 = :ID_Value'; 
FDQuery.MacroByname('OrderBy_clause').AsRaw := 'ORDER BY field1'; 

FDQuery.ParamByname('ID_Value').AsInteger := 1; 

FDQuery1.Open; 

Надеется, что это помогает

Смежные вопросы