Working with parameters Delphi XE7 Firedac - mysql

Any assistance here would be great.
I am trying to use parameters to dynamically change 'ORDER BY'
Below is the code I have tried but despite following the documentation I still get an error '[FIREDAC][PHYS][MYSQL] You have an error in your SQL syntax ... near "ORDER BY some_field" at line 4'
I have set ParamCreate to True
My database is 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;

You did not cite the exception message as it shows up. Here is the original message
[FireDAC][Phys][MySQL] You have an error in your SQL syntax ... near ''ORDER BY some_field'' at line 4.
compare to your cite
[FIREDAC][PHYS][MYSQL] You have an error in your SQL syntax ... near "ORDER BY some_field" at line 4
To avoid this for the future just press CTRL+C on the focused exception window and the complete message is inside your clipboard and can be pasted wherever you like
Now reading this, the error is now very clear.
You expect to get a statement like this
SELECT *
FROM my_table
LIMIT 1000
ORDER BY some_field
But using the parameter you will get the following statement
SELECT *
FROM my_table
LIMIT 1000
'ORDER BY some_field'
and that is exactly what the exception message is telling you.
Just check the exception message with the previous statement
... near 'ORDER BY some_field' at line 4.
and
... near ''ORDER BY some_field'' at line 4.
As a conclusion it is not possible to change the statement itself using parameters. You can only pass values as parameters for the statement.
And the correct statement should be anyway
SELECT *
FROM my_table
ORDER BY some_field
LIMIT 1000

Don't know if this helps.
But you can use the 'Macros' property of TFDQuery, like Parameter that are identified by the ':', the Macros are identified bye the '!', You can also combine Macros and Params. The Macros property works almost as the Params property. Use the TFDQuery.MacroByname to assign a Macro Value, and use the TFDQuery.MacroByname('MacroName').AsRaw to assign a string As-Is.
So your query should look like:
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;
Hope this helps

you need very simple SQL query:
FDQuery1.Close;
FDQuery1.SQL.Text := 'SELECT * FROM my_table';
FDQuery1.Open;
To set a limit of the record count, you can use property of the FDQuery1:
FDQuery1.FetchOptions.RecsMax := 1000;
To sort values you can use
FDQuery1.IndexFieldNames = 'field_name'
or
FDQuery1.IndexFieldNames = 'field_one_name;field_two_name'
instead of your code.

Edit: Oh, I didn't actually answer your question. So for FireDac, you can just set the FDQuery1.IndexFieldNames property to the name of the field/s you want to order by. No need to close and re-open your query, or change the SQL.
Previous answer: You cannot pass SQL code [EDIT: including ORDER BY etc.] in parameters, only parameter values, i.e. integers, strings etc.
This principle is extremely important, otherwise you could pass e.g.
FDQuery1.ParamByName('id').AsString := '; TRUNCATE TABLE my_table';
Executing your query would then delete everything in the table instead of doing what it's supposed to do. Or with a bit more work, your same query could return passwords, credit card numbers or whatever else is in your database. This would have been a huge vulnerability, and is known as SQL Injection. Please see for example:
http://www.w3schools.com/sql/sql_injection.asp
http://sqlmap.org/
http://hackaday.com/2014/09/01/gaining-access-to-the-oculus-developer-database

RXLIB has this functionality. It has the MACRO opttions, where you can write a code like this:
Select %fields_
from %table_
where %condition_
order by %order_
BUT it´s only for use qith BDE.
Will be wonderfull if someone rewrite the code to work with ADO ou FIREDAC.

Related

Basic Update Statement gets a "1111; Invalid use of Group Function" error on Kace SMA using MariaDB

I'm guessing this is something really simple as there's only really 3 lines of code here causing me a problem!
I'm creating a custom rule on the Kace SMA that selects tickets and updates the title field.
For those unfamiliar, the select statement in the SMA pulls your select into the <TICKET_IDS> variable for you to feed to the update statement. In the test area I'm running it in I'm getting ~12 ID's which matches what I would expect.
Select works fine, and then when the update runs via EXECUTE I get "[1111: Invalid use of group function] in..."
Both statements below. My initial thought was it's to do with WHERE/HAVING but I'm simply feeding the update a list and not doing anything other than that. I am familiar with standard SQL but hadn't really messed about with MariaDB/MySQL much until now so I apologise if it's a completely basic thing I've done.
SELECT HD_TICKET.ID
FROM HD_TICKET
WHERE HD_TICKET.HD_QUEUE_ID in (1)
AND HD_TICKET.IS_PARENT=TRUE
AND HD_TICKET.TITLE not like "CR%"
UPDATE HD_TICKET
SET HD_TICKET.TITLE = CONCAT('CR', ' ', CAST(COUNT(*) + 1 AS CHAR),' ', '-',' ', HD_TICKET.TITLE)
WHERE HD_TICKET.ID in (<TICKET_IDS>)

Select * from Select

Its very weird situation I know, nut I have got myself into it somehow. I have to connect to some other system service by passing some parameters in url.
In their service they are creating some query using parameter I pass.
For my case I have to pass 'Select' as a parameter name which is actually some class name on their side. So they end up in creating query as Select * from select
and some condition.
On execution I am getting error response as:
'There was a syntax error in a SQL query or filter expression at line
1, position 186. Saw \"Select\" but expected
'..SQL: \"SELECT col1, col2 FROM Select AS D where
some condition.
Can somebody help me on this.
Since Select is reserved word, you have to escape it by enclosing in backticks characters in order for MySQL to process your query:
select * from `select`
Its recommended not to use MySQL reserved keywords.. but if its necessary there is a solution..
Use this, it will work for you :
select * from yourdatabasename.select

case statement in MS Access query give error

I am using below query in Ms Access. And this gives me error Syntax error in your query expression CASE WHEN not ... . Can you please tell me what I am doing wrong? In Sql Server 2008 R2, the case statement runs correctly.
SELECT TableApron.RadButtonNo, TableApron.ShortName, QueryForNot1.InspectionDate, QueryForNot1.Findings, QueryForNot1.Status, QueryForNot1.Initials, TableApron.DeptName, TableApron.Lost, TableApron.InServelDate, TableApron.RemovedDate, TableApron.PrivateUserName, TableApron.PrivateUserEmail, TableApron.ApronType, TableApron.Manufacturer
FROM TableApron LEFT JOIN QueryForNot1 ON TableApron.RadButtonNo=QueryForNot1.RadButtonNoI
WHERE (((TableApron.Lost)="N" Or (TableApron.Lost)=[#Lost]) And ((TableApron.InServelDate) Is Null Or (TableApron.InServelDate) Between CDATE([#From]) And CDATE([#To]) Or (TableApron.InServelDate)<CDATE([#To])) And ((TableApron.RemovedDate) Is Null Or (TableApron.RemovedDate) Between CDATE([#From]) And CDATE([#To]) Or (TableApron.RemovedDate)>CDATE([#To])))
ORDER BY
CASE
WHEN not TableApron.RadButtonNo like '%[^0-9]%' THEN CONVERT(int,TableApron.RadButtonNo)
WHEN TableApron.RadButtonNo like '[0-9]%' THEN CONVERT(int,SUBSTRING(TableApron.RadButtonNo,1,PATINDEX('%[A-Z]%',TableApron.RadButtonNo)-1))
END,
CASE
WHEN not TableApron.RadButtonNo like '%[^0-9]%' THEN NULL
WHEN TableApron.RadButtonNo like '[0-9]%' THEN SUBSTRING(TableApron.RadButtonNo,PATINDEX('%[A-Z]%',TableApron.RadButtonNo),9000)
ELSE TableApron.RadButtonNo
END;
The CASE statement triggers the first reported error because it is not supported in Access SQL. Use IIf() instead as #Gustav suggested.
However then you will encounter additional errors because CONVERT, SUBSTRING, and PATINDEX are also not supported in Access SQL.
Instead of CONVERT, use CInt() to cast a value to Access Integer or CLng() for Long Integer. Or you could use Val() and let Access decide which numeric datatype to give you.
Instead of SUBSTRING, use Mid().
Instead of PATINDEX, use InStr().
Assuming those suggestions eliminate the syntax errors, you may still have an issue with the Like wildcard.
If you will be running the query from the query designer or elsewhere under DAO, Access expects * instead of % as the wildcard. % is the correct wild card only when the query is run from ADO/OleDb.

SSRS casting a parameter to decimal multi select

Im trying to cast a parameter in SSRS to a decimal. I have a in clause since its multi select. I can select 1 and it runs fine however if i select more than 1 it will say
"Incorrect syntax near the keyword 'as'."
I am casting my parameter in my where clause in my query statement.
WHERE LOAD_NO IN (CAST(#Load as DECIMAL))
I am confused as to why it would bring back the syntax error if I select more than one from list.
Thanks
I am confused as to why it would bring back the syntax error if I
select more than one from list.
Short answer
Because WHERE LOAD_NO IN (CAST(1,2,N as DECIMAL)) is not a valid T-SQL statement.
Long answer
When you use a multi-value parameter in a query, reporting services will generate different queries if your parameter contains 1 value, or multiple values.
Let's simplify your example to the following query:
SELECT * FROM TABLE WHERE LOAD_NO IN (#Load)
With only one value, the query will have the following format:
exec sp_executesql N'SELECT * FROM TABLE WHERE LOAD_NO IN (#Load)', N'#Load int', #Load=<YourValue>
It's a query with a parameter: #Load.
Now, with multiple values, the query will become
exec sp_executesql N'SELECT * FROM TABLE WHERE LOAD_NO IN (<YourValue1>, <YourValue2>,<YourValueN>)'
The #Load parameter has been replaced by the list of values.
So now my advise will be to rethink the design of your query and treat #Load as a list of values.
We cannot provide you the best solution because it really depends on the data and only you have all the details but I could still throw some ideas.
On the top of my head I could think of:
Cast LOAD_NO instead, but the execution plan may loose the benefits of indexes if any.
In most cases, using a IF EXISTS when possible instead of IN.
Use a subquery.
Do not hesitate to run a SQL Server Profiler to see the generated query if you have other issues.
I'm not sure what your data looks like, so I'm not sure if these options would help, but here's a couple suggestions:
Try putting the CAST on LOAD_NO instead:
WHERE CAST(LOAD_NO AS VARCHAR) IN (#Load)
Create a splitString function like the accepted post here (T-SQL split string) and access it in your WHERE clause:
WHERE LOAD_NO IN (SELECT CAST(val AS DECIMAL) FROM dbo.splitString(#Load, ','))

SQL returns no rows via myODB, but in SQL there are rows

I have an SQL table called "tbl_einheit". phpmyadmin shows more than 14.000 rows in the table. When accessing via webpage, the table is empty "eof".
I minimized the SQL Statment, and deleted all WHERE, ORDER BY elements, so that simply
SELECT * FROM tbl_einheit
is the statement. But it still returns an empty result set. I also tried
SELECT E . * FROM tbl_einheit E, ( SELECT #a := NULL ) AS init LIMIT 0,30
but also empty.
Any suggestions?
the reason is you have some data type in your mysql dtaabse that ADODB connector in ASSp can't recognize, so asp thinks it is EOF.
use CAST in MySQL to convert data type to something asp can understand, example:
SELECT CAST(SUM(Entry_Data_1) as UNSIGNED) as score FROM contests_entries
Put a trace in your code to make sure you are executing the code you think you are.
Double-check your connection string.