I want to display special symbols in my output.
For eg: My text may contain entity codes like <, > etc.
I want to display this as <, > in my output. I need to do this in SQL.
I googled about this and got a function,
select dbms_xmlgen.convert('ABC <; ',0) from dual
This does the reverse process, it generates the output as 'ABC <'
I tried with decoding but it does not work. I even changed the sql command as,
select dbms_xmlgen.convert('ABC <; ',1) from dual, where 1 is for entity_decode, but I don't get the desired output.
Instead of using DBMS_XMLGEN.convert, I used the function UTL_I18N.UNESCAPE_REFERENCE:
SELECT UTL_I18N.UNESCAPE_REFERENCE('ABC < ') FROM DUAL;
result:
ABC <
More information on the Oracle doc: http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/u_i18n.htm#i998992
Try something like:
SELECT DBMS_XMLGEN.CONVERT('ABC < ', DBMS_XMLGEN.ENTITY_DECODE) FROM DUAL
Also, see the Oracle docs for that.
EDIT:
Ok, so apparently this is a bug in some Oracle versions (9.2.0.1 and 10.1.0.2, as it seems). Somebody solved it by wrapping the function. I don't know how that's supposed to solve it, but it my be worth trying. Create a function like this:
CREATE OR REPLACE FUNCTION
xml_decode(
i_xml_string IN VARCHAR2
)
RETURN VARCHAR2
IS
BEGIN
RETURN
DBMS_XMLGEN.convert(
i_xml_string,
DBMS_XMLGEN.ENTITY_DECODE
);
END;
And use it instead:
SELECT xml_decode('ABC < ') FROM DUAL;
Let us know if that works.
Related
I made a query on one of the projects i m working on (On MariaDB 10.1.37):
SELECT * FROM table WHERE REGEXP_REPLACE(substring_index(product,' ',1), '[^a-zA-Z ]', '')='VALUE'
Where goal was:
1) from value select part till first space: example VALUE1 SOME OTHER to get VALUE1
2) to remove numbers and any other symbol: example VALUE1 to get VALUE
And query above does the trick as needed!
Issue is that on client side there is MySQL 5.7.27 and as we know REGEXP_REPLACE() came in MySQL on 8+ version
For now there are no options to upgrade client side to MySQL 8+ or migrate to MariaBD so the question is how and can i achieve the same result in MySQL 5.7.27?
I tried to search and tried WHERE substring_index(product,' ',1) REGEXP '^a-zA-Z' = 'VALUE' but REGEXP returns 1 or 0 and it is not what works for me as i need value. …
Any help?
Thanks in advance!
'Been searching for a solution as well since my mates are on MYSQL 5.5 and therefore they don't have REGEXP_REPLACE() either.
It's easy to find the solution on stackOverFlow for replacing just one char, but couldn't find for a string, therefore I've created that piece of code, it could help someone :
SET #string = 'I love shop it is a terrific shop, I love eveything about it';
SET #shop_code = 'shop';
SET #shop_date = CONCAT(#shop_code, '__', DATE_FORMAT(NOW(), '%Y_%m_%d__%Hh%im%ss'));
SET #part1 = SUBSTRING_INDEX(#string, #shop_code, 1);
SET #shop_nb = ROUND( (LENGTH(#string) - LENGTH(REPLACE(#string, #shop_code,''))) / LENGTH(#shop_code) );
SET #part2 = SUBSTRING_INDEX(#string, #shop_code, -#shop_nb);
SET #string = CONCAT(#part1, #shop_date, #part2);
SELECT #string;
This is not a final answer and if someone have a good or closer example to what i have asked then go ahead and post an answer. I would like to see it!
What i did is i just used LIKE
SELECT * FROM table WHERE substring_index(product,' ',1) LIKE 'VALUE%'
I know that this can show wrong data for some case but for my needs this way is acceptable.
This works in MySQL 5.7... This example would be extracting a UTM_Source parameter value from a URL's query string:
case when url like '%utm_source%' then
substring(
url,
locate('utm_source=',url)+char_length('utm_source='),
case when locate('&',url,locate('utm_source=',url)) = 0 then char_length(url)+1 else locate('&',url,locate('utm_source=',url)) end - (locate('utm_source=',url)+char_length('utm_source='))
) else NULL end utm_source;
Im creating Trigger FUnctions with PostgreSQL 9.1, how I tell it in this Trigger Function...
IF NEW.timetype = 'start' THEN
SELECT timestmp FROM tbl_ebscb_saaaa_log WHERE fnname = NEW.fnname AND timetype = 'start' ORDER BY stmtserial DESC LIMIT 1 INTO v_timestmp_start;
IF FOUND THEN
NEW.timetypespan := age(NEW.timestpm, v_timestmp_start);
ELSE
END IF;
I would like to... IF NOT FOUND then do nothing (like "pass" in python), what do I do? just leave it in blank??? Is not inside any loop.
Thanks Advanced.
PD: please if some could provide a good link with examples about basic postgresql work flow. Thanks Again.
There are at least two ways to do this in SQL generally:
First way is to not retrieve the value, but just check it. This would replace your select statement with an if exists statement. Use this method if you don't need to do anything else with the v_timestmp_start value.
It would look like: IF EXISTS (SELECT 1 FROM tbl WHERE ...) THEN ....
The other way would be to check the value of the variable which should be NULL if the select did not find anything. This would look very much like what you already have (but replace found with IF NOT NULL).
This would look like: IF v_timestmp_start IS NOT NULL THEN ....
And one more option that is unique to postgres. This looks exactly like what you already have (IF FOUND THEN ...).
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.
i have the following query
SELECT *
FROM `keywords`
WHERE name LIKE '%ba%'
ORDER BY LOCATE( 'ba', name ) , name
LIMIT 0 , 30
this query should sort result by the appreance of 'ba' in side keywords.name. but, I'm getting some weird behavior on some special chars:if - for example - i have the word Ghurabā the query
like %ba% will find it. but, it seems that locate(Ghurabā,ba) will return 0 - meaning as pattern was not found in string
any idea how to overcome this issue?
p.s -some useful data:
the result of the query above :
Ghurabā'
Khuṭabā'
qabā\
Ribāṭ
ba'urchi (cook)
Baghdad
...
note that it does work for "regular english characters" but there is a mismatch between the like and the locate function
Using Collcation: utf8_general_ci (got the same result with utf_unicode_ci)
mysql:effected version mysql 5.5/5.6 ( and probably lower)
EDIT:
expected result of the query above should be something like
'
Baghdad
ba'urchi (cook)
qabā\
Ribāṭ
Ghurabā'
Khuṭabā'
note : order by the distance of ab from the beginning of the word and then order by name
...
You should use BINARY operator to compare strings. Check these query -
SELECT
name,
name LIKE BINARY '%ba%',
name LIKE '%ba%',
LOCATE('ba', name)
FROM
`keywords`;
From the documentation:
LOCATE- this function is multi-byte safe
LIKE - performs matching on a per-character basis
In my Django app, I need to generate a MySQL query like this:
SELECT * FROM player WHERE (myapp_player.sport_id = 4 AND (myapp_player.last_name LIKE 'smi%'))
UNION
SELECT * FROM player WHERE (myapp_player.sport_id = 4 AND (myapp_player.first_name LIKE 'smi%'));
I can't use Q objects to OR together the __istartswith filters because the query generated by the Django ORM does not use UNION and it runs at least 40 times slower than the UNION query above. For my application, this performance is unacceptable.
So I'm trying stuff like this:
Player.objects.raw("SELECT * FROM myapp_player WHERE (sport_id = %%s AND (last_name LIKE '%%s%')) UNION SELECT * FROM sports_player WHERE (sport_id = %%s AND (first_name LIKE '%%s%'))", (sport.id, qword, sport.id, qword))
I apologize for the long one-liner, but I wanted to avoid using a triple-quoted string while trying to debug this type of issue.
When I execute or repr this queryset object, I get exceptions like this:
*** ValueError: unsupported format character ''' (0x27) at index 133
That's a single-quote in single quotes, not a triple-quote. If I get rid of the single-quotes around the LIKE clauses, then I get a similar exception about the close-paren ) character that follows the LIKE clause.
Apparently Django and MySQL disagree on the correct syntax for this query, but is there a syntax that will work for both?
Finally, I'm not sure that my %%s syntax for string interpolation is correct, either. The Django docs suggest that I should be able to use the regular %s syntax in the arguments for raw(), but several online resources suggest using %%s or ? as the placeholder for string interpolation in raw SQL.
My sincere thanks for just a little bit of clarity on this issue!
I got it to work like this:
qword = word + '%'
Player.objects.raw("SELECT * FROM myapp_player WHERE (sport_id = %s AND (last_name LIKE %s)) UNION SELECT * FROM myapp_player WHERE (sport_id = %s AND (first_name LIKE %s))", (sport.id, qword, sport.id, qword))
Besides the fact that %s seems to be the correct way to parameterize the raw query, the key here was to add the % wildcard to the LIKE clause before calling raw() and to exclude the single quotes from around the LIKE clause. Even though there are no quotes around the LIKE clause, quotes appear in the query ultimately sent to the MySQL sever.