MySQL Regex Replace Query - mysql

I have a field with this value:
TEST:ATEST:TESTA
And I want to replace "TEST" with "NEW", I have tried this query:
UPDATE `table` SET `field` = REPLACE(`field`, 'TEST', 'NEW') WHERE `field` REGEXP 'TEST';
The result was:
NEW:ANEW:NEWA
Q: How could I do the replacement query so the result would be like this:
NEW:ATEST:TESTA

It is a bit of a pain, but you can do it this way:
UPDATE `table`
SET field = substr(REPLACE(concat(':', field, ':'), ':TEST:', ':NEW:'),
2, length(REPLACE(concat(':', field, ':'), ':TEST:', ':NEW:')) - 2)
WHERE concat(':', field, ':') LIKE '%:TEST:%';
I prefer LIKE to REGEXP because there is the hope of being able to use an index. That is not a possibility in this case, but there is the hope.
This is delimiting the values with colons at the beginning and the end, and only replacing fully delimited values. The trick is to then remove the additional colons.

You can try http://sqlfiddle.com/#!9/4e66b/3
so the update query is (if table name = table1, field name = field1, and there is unique column id):
UPDATE `table1`
INNER JOIN
(SELECT id,
#set_idx:=FIND_IN_SET('TEST',REPLACE(field1,':',',')),
#set_size:=LENGTH(field1)-LENGTH(REPLACE(field1,':',''))+1,
CASE
WHEN #set_idx=1 THEN CONCAT('NEW',SUBSTRING(field1, 4))
WHEN #set_idx>1 THEN CONCAT(SUBSTRING_INDEX(field1, ':',#set_idx-1),':NEW', IF(#set_size>#set_idx,CONCAT(':',SUBSTRING_INDEX(field1, ':',-(#set_size-#set_idx))),''))
END as new
FROM table1
WHERE `field1` REGEXP '(^TEST$)|(^TEST:)|(:TEST$)|(:TEST:)'
) t
ON t.id = table1.id
SET table1.field1 = t.new;

Related

Why CONCAT does not insert text for the first time into mySQL table?

I am using UPDATE to insert simple text into a table where the field is MEDIUMTEXT (nullable field).
It is strange that it does not work when the field is null initially. If I manually enter at least a one character/space, then it's working.
I want to append the new text into existing text in the field.
UPDATE pen SET
PEN_STATUS = #PenStat,
PEN_STATUS_CHANGE_REASON = CONCAT(PEN_STATUS_CHANGE_REASON,'\n',ChangeDate,':',EmployeeID,':',ChangeReason)
WHERE PEN_ID = PenID;
Why is this?
CONCAT does not handle NULL values. As explained in the MySQL manual:
CONCAT() returns NULL if any argument is NULL.
You want to use COALESCE to handle that use case, like :
UPDATE pen SET
PEN_STATUS = #PenStat,
PEN_STATUS_CHANGE_REASON = CONCAT(
COALESCE(PEN_STATUS_CHANGE_REASON, ''),
'\n',
ChangeDate,
':',
EmployeeID,
':',
ChangeReason
)
WHERE PEN_ID = PenID;
Presumably, because something is NULL. Try using CONCAT_WS() instead:
UPDATE pen
SET PEN_STATUS = #PenStat,
PEN_STATUS_CHANGE_REASON = CONCAT_WS('\n',
PEN_STATUS_CHANGE_REASON,
CONCAT_WS(':', ChangeDate, EmployeeID, ChangeReason
)
)
WHERE PEN_ID = PenID;
CONCAT_WS() ignores NULL arguments. Plus, the separator only needs to be listed once.

Truncated incorrect DOUBLE value error on SQL statement?

I'm trying to append a string to an existing record in a MySQL Database:
UPDATE `db`.`tbl` SET field1 = IFNULL(field1, '') + ',' + '12/15/16: $50' WHERE field2 = 'xyz'
In MySQL, + is exactly what it suggests: addition. You are getting an error on arithmetic presumably because the strings are not converted to a number (fortunately -- otherwise you would silently get the wrong answer).
So, try this:
UPDATE `db`.`tbl`
SET field1 = CONCAT(COALESCE(field1, ''), ',', '12/15/16: $50')
WHERE field2 = 'xyz';
Or, if you don't want the comma if field1 is NULL:
UPDATE `db`.`tbl`
SET field1 = CONCAT(COALESCE(CONCAT(field1, ','), ''), '12/15/16: $50')
WHERE field2 = 'xyz';
to append in MySQL, use concat not + eg
select concat('something', 'something_else');
returns
somethingsomething_else
you can also use concat_ws (with separator)
select concat_ws('#','something', 'something_else')
returns
something#something_else

Find values that are start of SearchString

For a given search string s, I want to find values from an indexed varchar(255) field (~1m rows), so that s.startsWith(value) == true.
Example:
s = "hello world"
matches: "h", "hello", "hello world"
Is that possible?
You can use INSTR with opposite arguments than one would do in most cases:
SELECT *
FROM mytable
WHERE INSTR('hello world', mycol) = 1
This will return records where mycol has a substring of "hello world" starting at position 1. So any of the following will match:
h
he
hel
hell
hello
hello (with trailing space)
hello w
hello wo
hello wor
hello worl
hello world
You could maybe get better performance with the addition of the following redundant condition, which could hint the SQL engine to choose an index on mycol:
SELECT *
FROM mytable
WHERE INSTR('hello world', mycol) = 1
AND mycol like 'h%'
Just be aware that even with use of an index this does not guarantee a faster output. Imagine a table with values:
hel
helaaaaaaa
helaaaaaab
helaaaaaac
...(1000 more records like that, and finally:)
hello world
... then the engine would still scan all records, and only get the first and the last.
If you have an application executing this query, you could let it build the SQL dynamically, so that it looks like this:
SELECT *
FROM mytable
WHERE mycol IN ('h', 'he', 'hel', 'hell', 'hello', 'hello ', 'hello w',
'hello wo', 'hello wor', 'hello worl', 'hello world')
This would have potentially the best performance. If that doesn't do it, then certainly this elaborate SQL will do it:
SELECT * FROM mytable WHERE mycol = 'h'
UNION ALL
SELECT * FROM mytable WHERE mycol = 'he'
UNION ALL
SELECT * FROM mytable WHERE mycol = 'hel'
UNION ALL
SELECT * FROM mytable WHERE mycol = 'hell'
UNION ALL
SELECT * FROM mytable WHERE mycol = 'hello'
UNION ALL
SELECT * FROM mytable WHERE mycol = 'hello '
UNION ALL
SELECT * FROM mytable WHERE mycol = 'hello w'
UNION ALL
SELECT * FROM mytable WHERE mycol = 'hello wo'
UNION ALL
SELECT * FROM mytable WHERE mycol = 'hello wor'
UNION ALL
SELECT * FROM mytable WHERE mycol = 'hello worl'
UNION ALL
SELECT * FROM mytable WHERE mycol = 'hello world'
You want to use like for this:
where col like 'hello%' -- or whatever
or
where col like concat(#s, '%')
The reason for using like is that it can make use of an index, because the pattern does not start with wildcard characters.
EDIT:
I might have the logic backwards. If so, you can still use like:
where #s like concat(col, '%')
In this case, though, an index cannot be used, because the column is an argument to a function.
You can use "like" in sql.
select * from tableName
where columnName like 'h%'

MySQL, Concatenate two columns

There are two columns in a MySQL table: SUBJECT and YEAR.
I want to generate an alphanumeric unique number which holds the concatenated data from SUBJECT and YEAR.
How can I do this? Is it possible to use a simple operator like +?
You can use the CONCAT function like this:
SELECT CONCAT(`SUBJECT`, ' ', `YEAR`) FROM `table`
Update:
To get that result you can try this:
SET #rn := 0;
SELECT CONCAT(`SUBJECT`,'-',`YEAR`,'-',LPAD(#rn := #rn+1,3,'0'))
FROM `table`
You can use mysql built in CONCAT() for this.
SELECT CONCAT(`name`, ' ', `email`) as password_email FROM `table`;
change field name as your requirement
then the result is
and if you want to concat same field using other field which same then
SELECT filed1 as category,filed2 as item, GROUP_CONCAT(CAST(filed2 as CHAR)) as item_name FROM `table` group by filed1
then this is output
In php, we have two option to concatenate table columns.
First Option using Query
In query, CONCAT keyword used to concatenate two columns
SELECT CONCAT(`SUBJECT`,'_', `YEAR`) AS subject_year FROM `table_name`;
Second Option using symbol ( . )
After fetch the data from database table, assign the values to variable, then using ( . ) Symbol and concatenate the values
$subject = $row['SUBJECT'];
$year = $row['YEAR'];
$subject_year = $subject . "_" . $year;
Instead of underscore( _ ) , we will use the spaces, comma, letters,numbers..etc
In query, CONCAT_WS() function.
This function not only add multiple string values and makes them a single string value. It also let you define separator ( ” “, ” , “, ” – “,” _ “, etc.).
Syntax –
CONCAT_WS( SEPERATOR, column1, column2, ... )
Example
SELECT
topic,
CONCAT_WS( " ", subject, year ) AS subject_year
FROM table
I have two columns:
prenom and nom so to concatenate into a column with name chauffeur_sortant I used this script:
SELECT date as depart, retour, duree_mission, duree_utilisation, difference, observation, concat( tb_chaufeur_sortant.prenom, ' ', tb_chaufeur_sortant.nom) as chauffeur_sortant, concat(tb_chaufeur_entrant.prenom, ' ', tb_chaufeur_entrant.nom) as chauffeur_entrant
FROM tb_passation
INNER JOIN tb_vehicule
ON tb_vehicule.id = tb_passation.id_vehicule
INNER JOIN tb_chaufeur_sortant
ON tb_chaufeur_sortant.id = tb_passation.id_sortant
INNER JOIN tb_chaufeur_entrant
ON tb_chaufeur_entrant.id = tb_passation.id_entrant WHERE tb_vehicule.id = '';
$crud->set_relation('id','students','{first_name} {last_name}');
$crud->display_as('student_id','Students Name');

MySql: updating a column with the column's content plus something else

I'm don't have a lot of knowledge of MySql (or SQL in general) so sorry for the noobness.
I'm trying to update a bunch of String entries this way:
Lets say we have this:
commands.firm.pm.Stuff
Well I want to convert that into:
commands.firm.pm.print.Stuff
Meaning, Add the .print after pm, before "Stuff" (where Stuff can be any Alphanumerical String).
How would I do this with a MySql Query? I'm sure REGEXP has to be used, but I'm not sure how to go about it.
Thanks
Try something like this. It finds the last period and inserts your string there:
select insert(s, length(s) - instr(reverse(s), '.') + 1, 0, '.print')
from (
select 'commands.firm.pm.Stuff' as s
) a
To update:
update MyTable
set MyColumn = insert(MyColumn, length(MyColumn) - instr(reverse(MyColumn), '.') + 1, 0, '.print')
where MyColumn like 'commands.firm.pm.%'
Perhaps use a str_replace to replace commands.firm.pm to commands.firm.pm.print
$original_str = "commands.firm.pm.15hhkl15k0fak1";
str_replace("commands.firm.pm", "commands.firm.pm.print", $original_str);
should output: commands.firm.pm.print.15hhkl15k0fak1
then update your table with the new value...How to do it all in one query (get column value and do the update), I do not know. All I can think of is you getting the column value in one query, doing the replacement above, and then updating the column with the new value in a second query.
To update rows that end in '.Stuff' only:
UPDATE TableX
SET Column = CONCAT( LEFT( CHAR_LENGTH(Column) - CHAR_LENGTH('.Stuff') )
, '.print'
, '.Stuff'
)
WHERE Column LIKE '%.Stuff'
To update all rows - by appending .print just before the last dot .:
UPDATE TableX
SET Column = CONCAT( LEFT( CHAR_LENGTH(Column)
- CHAR_LENGTH(SUBSTRING_INDEX(Column, '.', -1))
)
, 'print.'
, SUBSTRING_INDEX(Column, '.', -1)
)
WHERE Column LIKE '%.%'