We currently have a database that has stored over 100,000 records of data over the years however in a structure that does not work anymore.
There is a field in the table called youtube_video
It has been storing all of the embed YouTube videos like this:
http://www.youtube.com/embed/3mHuu5NklOs?rel=0
http://www.youtube.com/embed/3mHuu5NklOs
We need to change it to:
https://www.youtube.com/watch?v=3mHuu5NklOs
Is there a way to write a query that makes this change with a single query?
You can use REGEXP_REPLACE :
SELECT REGEXP_REPLACE(
youtube_video,
'^http://www.youtube.com/embed/([^?]+).*',
'https://www.youtube.com/watch?v=\1'
) FROM mytable
Regex breakdown :
^ : start of string
http://www.youtube.com/embed/ : constant string part
([^?]+) : as many consecutive characters as possible others than a question mark ; the surrounding parentheses capture that part of the string, and make it available as \1 in the second argument to REGEXP_REPLACE()
.* : anything (until end of string)
This demo on DB Fiddle returns :
| youtube_video | new_youtube_video |
| ---------------------------------------------- | ------------------------------------------- |
| http://www.youtube.com/embed/3mHuu5NklOs?rel=0 | https://www.youtube.com/watch?v=3mHuu5NklOs |
| http://www.youtube.com/embed/3mHuu5NklOs | https://www.youtube.com/watch?v=3mHuu5NklOs |
If needed, you can easily turn this into an UPDATE :
UPDATE mytable
SET youtube_video = REGEXP_REPLACE(
youtube_video,
'^http://www.youtube.com/embed/([^?]+).*',
'https://www.youtube.com/watch?v=\1'
);
Related
I have a table which's name is users in my MySQL database, and I am using this DB with Ruby on Rails application with ORM structure for years. The table has id field and this field is configured as AI (auto-increment), BIGINT.
Example of my users table;
+----+---------+
| id | name |
+----+---------+
| 1 | John |
| 2 | Tommy |
| 3 | ... |
| 4 | ... |
| 5 | ... |
| 6 | ... |
+----+---------+
The problem I am facing is when I execute the following query I get unexpected rows.
SELECT * FROM users WHERE id = '1AW3F4SEFR';
This query is returning the exact same value with the following query,
SELECT * FROM users WHERE id = 1;
I do not know why SQL let me use strings in WHERE clause on a data type INT. And as we can see from the example, my DB converts the strings I gave to the integer at position 0. I mean, I search for 1AW3F4SEFR and I expect not to get any result. But SQL statement returns the results for id = 1.
In Oracle SQL, the behavior of this exact same query is completely different. So, I believe there is something different on MySQL. But I am not sure about what causes this.
As has been explained in the request comments, MySQL has a weird way of converting strings to numbers. It simply takes as much of a string from the left as is numeric and ignores the rest. If the string doesn't start with a number the conversion defaults to 0.
Examples: '123' => 123, '12.3' => 12.3, '.123' => 0.123, '12A3' => 12, 'A123' => 0, '.1A1.' => 0.1
Demo: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=55cd18865fad4738d03bf28082217ca8
That MySQL doesn't raise an error here as other DBMS do, can easily lead to undesired query results that get a long time undetected.
The solution is easy though: Don't let this happen. Don't compare a numeric column with a string. If the ID '1AW3F4SEFR' is entered in some app, raise an error in the app or even prevent this value from being entered. When running the SQL query, make sure to pass a numeric value, so '1AW3F4SEFR' cannot even make it into the DBMS. (Look up how to use prepared statements and pass parameters of different types to the database system in your programming language.)
If for some reason you want to pass a string for the ID instead (I cannot think of any such reason though) and want to make your query fail-safe by not returning any row in case of an ID like '1AW3F4SEFR', check whether the ID string represents an integer value in the query. You can use REGEXP for this.
SELECT * FROM users WHERE id = #id AND #id REGEXP '^[0-9]+$';
Thus you only consider integer ID strings and still enable the DBMS to use an index when looking up the ID.
Demo: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=56f8ee902342752933c20b8762f14dbb
I am trying to remove part of a string. But can't do it properly. String is like this: 4,290TL〜9,490TL So trying to remove after this 〜
I tried
UPDATE SET price = SUBSTRING_INDEX(price, '〜')
But not worked.
SUBSTRiNG_INDEX requires 3 parameters, the last one being the delimiter count. In this case you need to supply a count of 1, indicating that you want everything to the left of the first occurrence of the delimiter 〜. Additionally, you need to specify your table name in the query. Try this:
UPDATE yourtable SET price = SUBSTRING_INDEX(price, '〜', 1)
UPDATE SET price = SUBSTRING_INDEX(price, '〜', 1)
Please note the the strings you have shared with this question or comments uses DIFFERENT wavy line ("tilde") characters
# the tilde character used here is DIFFERENT to the next example
select substring_index('4,290TL〜9,490TL','〜',1)
;
+----+------------------------------------------------------+
| | substring_index('4,290TL〜9,490TL','〜',1) |
+----+------------------------------------------------------+
| 1 | 4,290TL |
# the tilde character is different to the one above
select substring_index('18,990万円(1戸)~28,790万円(1戸)','~',1)
;
+----+-----------------------------------------------------------+
| | substring_index('18,990万円(1戸)~28,790万円(1戸)','~',1) |
+----+-----------------------------------------------------------+
| 1 | 18,990万円(1戸) |
You will need to be CERTAIN the the tilde you use as delimiter is the one you use in substring_index() otherwise that function will just return the whole string.
I'm storing permissions into DB with Array JSON String, and i want select them by permission specific permission. at this time I'm selecting them like this:
1 | Dog | [3,4]
2 | Cat | [33,4]
3 | Tiger | [5,33,4]
4 | wolf | [3,5]
SELECT * FROM `pages` WHERE access REGEXP '([^"])3([^"])'
it works but not as it should work. This query gives me all records which contains 3 but also it gives which contains 33. my question is how i must format my regexp to get row by specific value into json string.
p.s i have mysql 5.5 so as i know on this version json functions is not supported
If you only have numbers in the fields, you can alter your regexp to only take values where the string you are looking for (here the '3') does not have another number immediately close to it :
SELECT * FROM `pages` WHERE access REGEXP '([^"0-9])3([^"0-9])'
REGEXP '[[:<:]]3[[:>:]]'
That is, use the "word boundary" thingies.
I have the following mysql table
+----------------+--------------------+
| ID | picture |
+----------------+--------------------+
| 10954 | picture/mypics.jpg |
+----------------+--------------------+
| 10759 | picture/mypics2.jpg|
+----------------+--------------------+
I need the existing filenames to be renamed to the ID for instance mypics.jpg renamed to 10954
How can i achieve this?
Thanks
UPDATE `following mysql table`
SET picture = CONCAT (
SUBSTR (picture, 0, CHAR_LENGTH(picture) - LOCATE('/', REVERSE(picture)),
'/',
ID
)
This replaces the part after the last slash with the value from the ID column. To my knowledge, MySQL has no function to find the last occurrence of a substring within a string, hence the funny construction with CHAR_LENGTH, LOCATE and REVERSE.
See MySQL String Functions for details.
I need to match a set of characters delimited by a hyphen - for example:
B-B/w-W/Br-W-Br
Where the / are part of what I need, up to 20 spaces.
G-R-B, G/R-B-B/W-O
So I need a regex that covers between the -'s in any order (G-R-B could also be R-B-G)
I've been playing around with a bunch of combo's, but I can't come up with something that will match any order.
The plan is to search this way using mysql. So, it'll be something like
select * from table1 where pinout REGEXP '';
I just can't get the regex right :/
Description
This expression will match the string providing each of the hyphen delimited values are included in the string. The color values can appear in the string in any order so this expression will match W/Br-b-B/w and B/w-W/Br-b... or any other combinations which include those colors.
^ # match the start to of the string
(?=.*?(?:^|-)W\/Br(?=-|$)) # require the string to have a w/br
(?=.*?(?:^|-)b(?=-|$)) # require the string to have a b
(?=.*?(?:^|-)B\/w(?=-|$)) # require the string to have a b/w
.* # match the entire string
MySql doesn't really support the look arounds so this will need to be broken into a group of where statements
mysql> SELECT * FROM dog WHERE ( color REGEXP '.*(^|-)W\/Br(-|$)' and color REGEXP '.*(^|-)b(-|$)' and color REGEXP '.*(^|-)B\/w(-|$)' );
+-------+--------+---------+------+------------+---------------------+
| name | owner | species | sex | birth | color |
+-------+--------+---------+------+------------+---------------------+
| Claws | Gwen | cat | m | 1994-03-17 | B-B/w-W/Br-W-Br |
| Buffy | Harold | dog | f | 1989-05-13 | G-R-B, G/R-B-B/W-O |
+-------+--------+---------+------+------------+---------------------+
See also this working sqlfiddle: http://sqlfiddle.com/#!2/943af/1/0
Using a regex in conjunction with a MySql where statement can be found here: http://dev.mysql.com/doc/refman/5.1/en/pattern-matching.html
I might have misunderstood from your example, try this:
-*([a-zA-Z/]+)-*
The capture region can be altered to include your specific letters of interest, e.g. [GRBWOgrbwo/].
Edit: I don't think this will help you in the context you're using it, but I'll leave it here for posterity.