I have developed a function for split string in tsql but mysql don't have some built in functions. I needed to function in MYSQL as i am new in mysql. Function should accept 2 parameters
1. String to be split
2. separator (',' or whatever)
Kindly reply me.
i had found solution on the internet you can into that.
DELIMITER //
DROP FUNCTION IF EXISTS `splitAndTranslate` //
CREATE FUNCTION splitAndTranslate(str TEXT, delim VARCHAR(124))
RETURNS TEXT
DETERMINISTIC
BEGIN
DECLARE i INT DEFAULT 0; -- total number of delimiters
DECLARE ctr INT DEFAULT 0; -- counter for the loop
DECLARE str_len INT; -- string length,self explanatory
DECLARE out_str text DEFAULT ''; -- return string holder
DECLARE temp_str text DEFAULT ''; -- temporary string holder
DECLARE temp_val VARCHAR(255) DEFAULT ''; -- temporary string holder for query
-- get length
SET str_len=LENGTH(str);
SET i = (LENGTH(str)-LENGTH(REPLACE(str, delim, '')))/LENGTH(delim) + 1;
-- get total number delimeters and add 1
-- add 1 since total separated values are 1 more than the number of delimiters
-- start of while loop
WHILE(ctr<i) DO
-- add 1 to the counter, which will also be used to get the value of the string
SET ctr=ctr+1;
-- get value separated by delimiter using ctr as the index
SET temp_str = REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, ctr), LENGTH(SUBSTRING_INDEX(str, delim,ctr - 1)) + 1), delim, '');
-- query real value and insert into temporary value holder, temp_str contains the exploded ID
SELECT <real_value_column> INTO temp_val FROM <my_table> WHERE <table_id>=temp_str;
-- concat real value into output string separated by delimiter
SET out_str=CONCAT(out_str, temp_val, ',');
END WHILE;
-- end of while loop
-- trim delimiter from end of string
SET out_str=TRIM(TRAILING delim FROM out_str);
RETURN(out_str); -- return
END//
reference http://www.slickdev.com/2008/09/15/mysql-query-real-values-from-delimiter-separated-string-ids/
In mysql they they dont support some functionality like sqlserver. so spliting will be difficult in mysql
SELECT e.`studentId`, SPLIT(",", c.`courseNames`)[e.`courseId`]
FROM ..
SELECT TRIM(SUBSTRING_INDEX(yourcolumn,',',1)), TRIM(SUBSTRING_INDEX(yourcolumn,',',-1)) FROM yourtable
CREATE FUNCTION [dbo].[SplitString]
(
#RowData nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
--Id int identity(1,1),
Data nvarchar(100)
)
AS
BEGIN
Declare #Cnt int
Set #Cnt = 1
While (Charindex(#SplitOn,#RowData)>0)
Begin
Insert Into #RtnValue (data)
Select
Data = ltrim(rtrim(Substring(#RowData,1,Charindex(#SplitOn,#RowData)-1)))
Set #RowData = Substring(#RowData,Charindex(#SplitOn,#RowData)+1,len(#RowData))
Set #Cnt = #Cnt + 1
End
Insert Into #RtnValue (data)
Select Data = ltrim(rtrim(#RowData))
Return
END
Related
I am new to mySQL and got the exercise to implement a function which merges columns from one table and outputs it as a string, separated by CR (a CR after each record, i.e. separate the records by “\n”).
I have tried it already, but there appears an error which say: "SELECT MergeTablesAndOutputString(1) LIMIT 0, 1000.
What do I have to do differently that it works?
DELIMITER //
CREATE FUNCTION MergeTablesAndOutputString
(owner_id int)
RETURNS varchar(50)
DETERMINISTIC
BEGIN
DECLARE bname varchar(30);
DECLARE apno int(30);
DECLARE gno int(30);
set bname = Building.buildingName;
set apno = Building.apartmentno;
set gno = Building.garageno;
RETURN CONCAT(bname, '\n' + apno, ' \n', gno);
END//
DELIMITER ;
I need to convert a function from PostgreSQL toMySql. I need to remove the special characters from a string uri.
CREATE OR REPLACE FUNCTION name2uri(text)
RETURNS text
IMMUTABLE
STRICT
LANGUAGE SQL
AS $$
SELECT REPLACE(TRIM(regexp_replace(translate(
LOWER($1),
'áàâãäåāăąèééêëēĕėęěìíîïìĩīĭḩóôõöōŏőùúûüũūŭůäàáâãåæçćĉčöòóôõøüùúûßéèêëýñîìíïş',
'aaaaaaaaaeeeeeeeeeeiiiiiiiihooooooouuuuuuuuaaaaaaeccccoooooouuuuseeeeyniiiis'
), '[^a-z0-9\-]+', ' ', 'g')),' ', '-');
$$;
how do I do that? Tks.
Solution
DROP FUNCTION IF EXISTS translate;
DELIMITER //
CREATE FUNCTION translate(subject varchar(255), what varchar(255), replace_to varchar(255))
RETURNS varchar(255)
DETERMINISTIC
begin
declare c int unsigned default 0;
declare result varchar(255);
set result = subject;
while c <= length(subject) do
set result = replace(result, mid(what, c, 1), mid(replace_to, c, 1) );
set c=c+1;
end while;
return result;
end
and
DROP FUNCTION IF EXISTS name2uri;
DELIMITER //
CREATE FUNCTION name2uri(i text)
RETURNS longtext
DETERMINISTIC
BEGIN
declare result longtext;
set result = REPLACE(TRIM(regexp_replace(translate(
LOWER(i),
'áàâãäåāăąèééêëēĕėęěìíîïìĩīĭḩóôõöōŏőùúûüũūŭůäàáâãåæçćĉčöòóôõøüùúûßéèêëýñîìíïş',
'aaaaaaaaaeeeeeeeeeeiiiiiiiihooooooouuuuuuuuaaaaaaeccccoooooouuuuseeeeyniiiis'
), '[^a-z0-9-]+', ' ',1,0,'c')),' ', '-');
return result;
end
select name2uri(' fáBIO rodrígues') with space before or after the string comes out ok! --> fabio-rodrigues
select name2uri('fáBIO rodrígues') without space before or after the string quits not ok! --> fabio-rodr-gues (the char i is replace by -)
Why did not correctly replace the í character with i?
I need to sort below cell values using mysql
Example:
cell contain red,blue,green
But I want that in alphabetic order.
Steps to do this,
1.First you need to make a procedure call for sorting values
2.Call your procedure then
Here is the code to create mysql procedure
-- sort comma separated substrings with unoptimized bubble sort
DROP FUNCTION IF EXISTS sortString;
DELIMITER |
CREATE FUNCTION sortString(inString TEXT) RETURNS TEXT
BEGIN
DECLARE delim CHAR(1) DEFAULT ','; -- delimiter
DECLARE strings INT DEFAULT 0; -- number of substrings
DECLARE forward INT DEFAULT 1; -- index for traverse forward thru substrings
DECLARE backward INT; -- index for traverse backward thru substrings, position in calc. substrings
DECLARE remain TEXT; -- work area for calc. no of substrings
-- swap areas TEXT for string compare, INT for numeric compare
DECLARE swap1 TEXT; -- left substring to swap
DECLARE swap2 TEXT; -- right substring to swap
SET remain = inString;
SET backward = LOCATE(delim, remain);
WHILE backward != 0 DO
SET strings = strings + 1;
SET backward = LOCATE(delim, remain);
SET remain = SUBSTRING(remain, backward+1);
END WHILE;
IF strings < 2 THEN RETURN inString; END IF;
REPEAT
SET backward = strings;
REPEAT
SET swap1 = SUBSTRING_INDEX(SUBSTRING_INDEX(inString,delim,backward-1),delim,-1);
SET swap2 = SUBSTRING_INDEX(SUBSTRING_INDEX(inString,delim,backward),delim,-1);
IF swap1 > swap2 THEN
SET inString = TRIM(BOTH delim FROM CONCAT_WS(delim
,SUBSTRING_INDEX(inString,delim,backward-2)
,swap2,swap1
,SUBSTRING_INDEX(inString,delim,(backward-strings))));
END IF;
SET backward = backward - 1;
UNTIL backward < 2 END REPEAT;
SET forward = forward +1;
UNTIL forward + 1 > strings
END REPEAT;
RETURN inString;
END |
DELIMITER ;
To make procedure call just you have to use,
-- example call:
SET #Xstr = "red,blue,green"; // for query purpose only you need to write within (SQL Query here for that row)
SELECT sortString(#Xstr) AS s1
Please see the documentation guide map
Click here to read
Also there is an alternative way to do if you are interested to study is that about FIND_IN_SET, please you can find some idea from one of the question from stackoverflow. Click here to read
You can create a function which sorts the items in the column:
create function f_comma_list_order ( t text )
returns text
begin
declare v_c int;
drop temporary table if exists tmp;
create temporary table tmp ( v text );
set v_c = 1;
while( v_c > 0 ) do
select locate(',', t) into v_c;
if (v_c>0) then
insert into tmp select substr(t, 1, v_c-1);
set t = substr(t, v_c+1);
else
insert into tmp values (t);
end if;
end while;
select group_concat(v order by v) into t
from tmp;
return t;
end
and then call the function:
select f_comma_list_order('red,green,blue')
I'm trying to figure out how to create a single MySQL query that will allow me to display only the next 10 characters following the string "filter" in the Message field. The string "filter" appears at various positions in each record, so I can't use a position filter.
I've been trying to use something like like what I have below, however I've been unable to get the correct query.
SELECT RIGHT(Message,LOCATE('filter',Message) - 10) FROM table
The Message field records within the table looks like:
QgySSW8fwD25iQ.filter0019p3las1-31205-59C3D
6t2fJw.filter0010p3las1-9745-59
filter0025p3las1-13130-59C3D317
And I'm looking for them to look like this after the query:
0019p3las1
0010p3las1
0025p3las1
Any help is greatly appreciated.
Use a combination of LOCATE() within SUBSTRING(). See this SQL Fiddle
CREATE TABLE Table1
(`message` varchar(200))
;
INSERT INTO Table1
(`message`)
VALUES
('QgySSW8fwD25iQ.filter0019p3las1-31205-59C3D'),
('6t2fJw.filter0010p3las1-9745-59'),
('filter0025p3las1-13130-59C3D317')
;
Query 1:
select
SUBSTRING(message,LOCATE('filter',Message)+6,10)
from table1
Note that the +6 is to offset for the length of "filter" because LOCATE finds the position of the "f" and you then need to add 6 for the other characters "ilter". Once that number is determined then just get the next 10 characters.
Results:
| SUBSTRING(message,LOCATE('filter',Message)+6,10) |
|--------------------------------------------------|
| 0019p3las1 |
| 0010p3las1 |
| 0025p3las1 |
See SQLFiddle.
Result table structure
Create table resulttbl (
id int(6) primary key auto_increment ,
resultFIlter varchar(1000)
);
Function to split string
CREATE FUNCTION strSplit(x VARCHAR(65000), delim VARCHAR(12), pos INTEGER)
RETURNS VARCHAR(65000)
BEGIN
DECLARE output VARCHAR(65000);
SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos)
, LENGTH(SUBSTRING_INDEX(x, delim, pos - 1)) + 1)
, delim
, '');
IF output = '' THEN SET output = null; END IF;
RETURN output;
END;
Stored procedure to split and insert into result table
CREATE PROCEDURE FilterTable()
BEGIN
DECLARE i INTEGER;
DECLARE endpos INTEGER;
DECLARE fullstr VARCHAR(1000);
DECLARE result VARCHAR(1000);
SET fullstr = 'QgySSW8fwD25iQ.filter0019p3las1-31205-59C3D 6t2fJw.filter0010p3las1-9745-59 filter0025p3las1-13130-59C3D317';
SET i = 2;
SET endpos=LENGTH(fullstr) - LENGTH(REPLACE(fullstr, 'filter', '')) ;
delete from resulttbl;
REPEAT
SET result=strSplit(fullstr, 'filter', i);
IF result IS NOT NULL THEN
SET result=LEFT(result,10);
INSERT INTO resulttbl (resultFIlter) values(result);
END IF;
SET i = i + 1;
UNTIL i >= endpos
END REPEAT;
END ;
Call the procedure using the statement CALL FilterTable().
Now the result of your procedure is available on the table resulttbl.
You can get the values from that table using select statement as SELECT * from resulttbl.
Result
id resultFIlter
1 0019p3las1
2 0010p3las1
3 0025p3las1
I want to be able to pass an "array" of values to my stored procedure, instead of calling "Add value" procedure serially.
Can anyone suggest a way to do it? am I missing something here?
Edit: I will be using PostgreSQL / MySQL, I haven't decided yet.
As Chris pointed, in PostgreSQL it's no problem - any base type (like int, text) has it's own array subtype, and you can also create custom types including composite ones. For example:
CREATE TYPE test as (
n int4,
m int4
);
Now you can easily create array of test:
select ARRAY[
row(1,2)::test,
row(3,4)::test,
row(5,6)::test
];
You can write a function that will multiply n*m for each item in array, and return sum of products:
CREATE OR REPLACE FUNCTION test_test(IN work_array test[]) RETURNS INT4 as $$
DECLARE
i INT4;
result INT4 := 0;
BEGIN
FOR i IN SELECT generate_subscripts( work_array, 1 ) LOOP
result := result + work_array[i].n * work_array[i].m;
END LOOP;
RETURN result;
END;
$$ language plpgsql;
and run it:
# SELECT test_test(
ARRAY[
row(1, 2)::test,
row(3,4)::test,
row(5,6)::test
]
);
test_test
-----------
44
(1 row)
If you plan to use MySQL 5.1, it is not possible to pass in an array.
See the MySQL 5.1 faq
If you plan to use PostgreSQL, it is possible look here
I don't know about passing an actual array into those engines (I work with sqlserver) but here's an idea for passing a delimited string and parsing it in your sproc with this function.
CREATE FUNCTION [dbo].[Split]
(
#ItemList NVARCHAR(4000),
#delimiter CHAR(1)
)
RETURNS #IDTable TABLE (Item VARCHAR(50))
AS
BEGIN
DECLARE #tempItemList NVARCHAR(4000)
SET #tempItemList = #ItemList
DECLARE #i INT
DECLARE #Item NVARCHAR(4000)
SET #tempItemList = REPLACE (#tempItemList, ' ', '')
SET #i = CHARINDEX(#delimiter, #tempItemList)
WHILE (LEN(#tempItemList) > 0)
BEGIN
IF #i = 0
SET #Item = #tempItemList
ELSE
SET #Item = LEFT(#tempItemList, #i - 1)
INSERT INTO #IDTable(Item) VALUES(#Item)
IF #i = 0
SET #tempItemList = ''
ELSE
SET #tempItemList = RIGHT(#tempItemList, LEN(#tempItemList) - #i)
SET #i = CHARINDEX(#delimiter, #tempItemList)
END
RETURN
END
You didn't indicate, but if you are referring to SQL server, here's one way.
And the MS support ref.
For PostgreSQL, you could do something like this:
CREATE OR REPLACE FUNCTION fnExplode(in_array anyarray) RETURNS SETOF ANYELEMENT AS
$$
SELECT ($1)[s] FROM generate_series(1,array_upper($1, 1)) AS s;
$$
LANGUAGE SQL IMMUTABLE;
Then, you could pass a delimited string to your stored procedure.
Say, param1 was an input param containing '1|2|3|4|5'
The statement:
SELECT CAST(fnExplode(string_to_array(param1, '|')) AS INTEGER);
results in a result set that can be joined or inserted.
Likewise, for MySQL, you could do something like this:
DELIMITER $$
CREATE PROCEDURE `spTest_Array`
(
v_id_arr TEXT
)
BEGIN
DECLARE v_cur_position INT;
DECLARE v_remainder TEXT;
DECLARE v_cur_string VARCHAR(255);
CREATE TEMPORARY TABLE tmp_test
(
id INT
) ENGINE=MEMORY;
SET v_remainder = v_id_arr;
SET v_cur_position = 1;
WHILE CHAR_LENGTH(v_remainder) > 0 AND v_cur_position > 0 DO
SET v_cur_position = INSTR(v_remainder, '|');
IF v_cur_position = 0 THEN
SET v_cur_string = v_remainder;
ELSE
SET v_cur_string = LEFT(v_remainder, v_cur_position - 1);
END IF;
IF TRIM(v_cur_string) != '' THEN
INSERT INTO tmp_test
(id)
VALUES
(v_cur_string);
END IF;
SET v_remainder = SUBSTRING(v_remainder, v_cur_position + 1);
END WHILE;
SELECT
id
FROM
tmp_test;
DROP TEMPORARY TABLE tmp_test;
END
$$
Then simply CALL spTest_Array('1|2|3|4|5') should produce the same result set as the above PostgreSQL query.
Thanks to JSON support in MySQL you now actually have the ability to pass an array to your MySQL stored procedure. Create a JSON_ARRAY and simply pass it as a JSON argument to your stored procedure.
Then in procedure, using MySQL's WHILE loop and MySQL's JSON "pathing" , access each of the elements in the JSON_ARRAY and do as you wish.
An example here https://gist.githubusercontent.com/jonathanvx/513066eea8cb5919b648b2453db47890/raw/22f33fdf64a2f292688edbc67392ba2ccf8da47c/json.sql
Incidently, here is how you would add the array to a function (stored-proc) call:
CallableStatement proc = null;
List<Integer> faultcd_array = Arrays.asList(1003, 1234, 5678);
//conn - your connection manager
conn = DriverManager.getConnection(connection string here);
proc = conn.prepareCall("{ ? = call procedureName(?) }");
proc.registerOutParameter(1, Types.OTHER);
//This sets-up the array
Integer[] dataFaults = faultcd_array.toArray(new Integer[faultcd_array.size()]);
java.sql.Array sqlFaultsArray = conn.createArrayOf("int4", dataFaults);
proc.setArray(2, sqlFaultsArray);
//:
//add code to retrieve cursor, use the data.
//: