MySQL function doesn't work with unicode strings - mysql

I have a MySQL function which does some string replacement in a specified string. I simplyfied this function to return it's argument.
CREATE FUNCTION replace_details(
id INT UNSIGNED,
message VARCHAR(1000))
RETURNS VARCHAR(1000) LANGUAGE SQL
BEGIN
RETURN message;
END;
;;
This function is called from before insert trigger, so the inserted string is modified. Everything works as expected while I'm using english text, but as soon as I'm trying to insert something else (for example russian) it makes my string unreadable. Actually I get only ? sign in a database. If I'm using any other function in trigger it works fine
For example:
SET NEW.message = CONCAT(NEW.message, ' test');
but as soon as I'm using my custom function which actually does nothing, but returns what it got, inserted string becomes unreadable.
I guess I need to somehow specify that my function works with unicode, but how?
MySQL server version: 5.7.1-m11

I found it.
CREATE FUNCTION replace_details(
id INT UNSIGNED,
message VARCHAR(1000) CHARACTER SET UTF8)
RETURNS VARCHAR(1000) CHARACTER SET UTF8 LANGUAGE SQL
BEGIN
RETURN message;
END;
;;
works!

Related

Error 1415: Not allowed to return a result set from a function

CREATE FUNCTION `remover_acentos` (text_1 text)
RETURNS text
select
replace(text_1,'áâãäéêëíîÏóöôõúûüÁÂÃÄÉÊËÍÎÏÓÖÔÕÚÛÜçÇ','aaaaeeeiiioooouuuAAAAEEEIIIOOOOUUUcC');
The function above is throwing the error below.
Error 1415: Not allowed to return a result set from a function
Why is this error occurring?
What's the SELECT doing there? That's causing the error. Use RETURN to return a scalar value.
CREATE FUNCTION `remover_acentos` (text_1 text)
RETURNS text
RETURN replace(text_1,'áâãäéêëíîÏóöôõúûüÁÂÃÄÉÊËÍÎÏÓÖÔÕÚÛÜçÇ','aaaaeeeiiioooouuuAAAAEEEIIIOOOOUUUcC');
But this won't do what you want, I guess. If you want to replace any single occurrence of one of the characters, you'll need more than one replace() -- for each character, use one. Like
DELIMITER $$
CREATE FUNCTION `remover_acentos` (text_1 text)
RETURNS text
BEGIN
SET text_1 = replace(text_1,'á','a');
SET text_1 = replace(text_1,'à','a');
...
RETURN text_1;
END;$$
DELIMITER ;

sql create a function

Could someone please help me with this one?
So I need to write a user input function in which I need to concatenate two strings. When outputted, there must be a space between the two strings, note there is not a space in the two strings when inputting them. Test functions with the following, String 1: Spring, String 2: Break!
This is my solution:
create function concatenate(X CHAR,Y CHAR)
Returns CHAR(50)
Return concat(X, ' ', Y);
select concatenate('Spring','Break')
However, the problem is that sql only returns the first letter of each word, which is "S B". But I want it to be "Spring Break"
Any ideas on this one? Helps are very appreciated
Supply a length for the input parameters as well:
create function concatenate(X CHAR(24),Y CHAR(24))
Returns CHAR(50)
Return concat(X, ' ', Y);
select concatenate('Spring','Break')
You need to define the size when you declare the argument.
create function con(X char(50), Y char(50))
returns char(100)
You have to specify the size of CHAR(), otherwise it will use the default CHAR(1), and you can't get want you want.
eg:
create function hello(x char(10),y char(10))
returns char(30) deterministic
return concat(x,' ',y)`
select hello('Hello','World');
Hello World

How store as JSON the new data inside a trigger in PostgreSQL?

I try to do as explained in:
https://wiki.postgresql.org/wiki/Audit_trigger
Auditing values as JSON
For PostgreSQL 9.2, or 9.1 with the fantastic json_91 addon, you can
log the old and new values in the table as structured json instead of
flat text, giving you much more power to query your audit history.
Just change the types of v_old_data, v_new_data, original_data and
new_data from TEXT to json, then replace ROW(OLD.) and ROW(NEW.)
with row_to_json(OLD) and row_to_json(NEW) respectively.
However this get me a error:
CREATE OR REPLACE FUNCTION add_log (name text, Action TEXT, data jsonb, OUT RETURNS BOOLEAN)
AS $$
BEGIN
RETURNS = true;
END;
$$
LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION log_city() RETURNS TRIGGER AS
$$
DECLARE
v_new_data jsonb;
BEGIN
IF (TG_OP = 'UPDATE') THEN
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
v_new_data := row_to_jsonb(NEW);
EXECUTE add_log('City', 'City.New', v_new_data);
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
$$ LANGUAGE plpgsql;
INSERT INTO Location (city, state, country) values ('a', 'b' , 'c')
It say:
ERROR: function row_to_jsonb(location) does not exist
If I put v_new_data := row_to_jsonb(ROW(NEW)); then I get:
ERROR: function row_to_jsonb(record) does not exist
It's stated in the documentation that
Table 9-42 shows the functions that are available for creating json
and jsonb values. (There are no equivalent functions for jsonb, of the
row_to_json and array_to_json functions. However, the to_jsonb
function supplies much the same functionality as these functions
would.)
thus it's row_to_json that has to be used. a row_to_jsonb does not exists but row_to_json produces the desired result for the JSONB type as well.

Calling functions within function in MySQL returns NULL

I don't understand why when I call my SQL Function inside another Function values are lost. Basically I have something like this:
CREATE FUNCTION `myCustomFunctionA`(paramOne INTEGER, paramTwo INTEGER) RETURNS INT(11)
BEGIN
DECLARE outputOne INT(11);
DECLARE outputTwo INT(11);
SET outputOne = myCustomFunctionB(paramOne);
SET outputTwo = myCustomFunctionB(paramTwo);
RETURN myCustomFunctionC(outputOne, outputTwo);
END
Please note that all of these functions return each an integer when called outside myCustomFunctionA. I.E: Running SELECT myCustomFunctionB(paramTwo); actually returns X value and same for paramOne. However when these functions are called inside myCustomFunctionA it's always returning NULL.
So far I tried to return directly paramOne and paramTwo and values are correct. But if I set function to return outputOne or outputTwo after running myCustomFunctionB then they'd also return NULL.
This seems to be something silly I'm missing but I can't see it so any help or tip in the right direction would be really apprecciated. Thanks.

Mysql recursive procedure

I have a table name css_diectory with 3 columns directory_id, directory-name and root_directory. I am storing hierarchical directory structure in this table. I have written a procedure to retrieve all the descendants given the directory_id. But it doesn't work. Can anyone please help me.
Here is the procedure
CREATE PROCEDURE getDescendants
(IN rootId varchar(32), INOUT desecendantsFolderId varchar(3200))
BEGIN
DECLARE endOfRecord INTEGER DEFAULT 0;
DECLARE folderId varchar(32) DEFAULT "";
DECLARE folderName varchar(32) DEFAULT "";
DECLARE folderCursor CURSOR FOR
Select directory_id, directory_name from css_directory where root_directory=rootId;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET endOfRecord = 1;
OPEN folderCursor;
getFolderId: LOOP
FETCH folderCursor INTO folderId, folderName;
IF endOfRecord = 1 THEN
LEAVE getFolderId;
END IF;
Call getDescendants(folderId,desecendantsFolderId);
SET desecendantsFolderId = CONCAT(folderId,",",desecendantsFolderId);
call getDescendants(folderId,desecendantsFolderId);
END LOOP getFolderId;
END
Edit: The output of this procedure is always a null set. It does not produce any error
I'm not 100% sure I follow what you're doing, but it looks like there's a problem here:
SET desecendantsFolderId = CONCAT(folderId,",",desecendantsFolderId);
When any argument to CONCAT() is null, then the return value is null. Presumably descendantsFolderId is initially null, and if so, I don't see where that would change.
There are several ways to remedy this, but here is one of them:
SET desecendantsFolderId = NULLIF(CONCAT_WS(",",folderId,desecendantsFolderId),"");
CONCAT_WS() is like CONCAT(), except the first argument is used as a separator amd null arguments beyond the first one are disregarded, and empty string is returned if all subsequent arguments are null. NULLIF() is probably not technically needed, based on the rest of the code, but will ensure that the final result of CONCAT_WS() will be turned back to null if the input args are indeed all null.