Setting a wordpress project to its staging environment, I have ran into an issue regarding paths that were set for the development environment, and don't fit the ones in staging.
So I need to update the paths in the database, from C:\xampp\htdocs\site.com to /var/www/site.com
At first, I tried replacing, the same way I replaced the urls:
update `wp_slider` set `url` = replace(`url`, 'http://local.', 'http://');
Then the paths:
update `wp_slider` set `path` = replace(`path`, 'C:\xampp\htdocs\site.com', '/var/www/site.com');
Which actually didn't work. Then I tried a SELECT to see what rows can I retrieve:
SELECT * FROM `wp_slider` WHERE `path` LIKE "%C:\xampp\htdocs\site.com%"
Which will return an empty result. What am I missing?
Forgot to mention, that I tried escaping the \ by doing \\ and I still get no result
A full path of what I'm trying to replace would be like: C:\xampp\htdocs\site.com/wp-content/plugins/slider/skins/slider\circle\circle.css
That's roughly the way to go:
mysql> SELECT REPLACE('C:\\xampp\\htdocs\\site.com\\foo\\bar.txt', 'C:\\xampp\\htdocs\\site.com', '/var/www/site.com');
+----------------------------------------------------------------------------------------------------------+
| REPLACE('C:\\xampp\\htdocs\\site.com\\foo\\bar.txt', 'C:\\xampp\\htdocs\\site.com', '/var/www/site.com') |
+----------------------------------------------------------------------------------------------------------+
| /var/www/site.com\foo\bar.txt |
+----------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql>
If you get zero matches that's because your DB records do not contain what you think they do. Make sure you don't have blanks or control characters. If your MySQL client does not make it easy to spot such things, you can always use HEX():
SELECT path, HEX(path)
FROM wp_slider
WHERE path NOT LIKE "C:\\xampp\\htdocs\\site.com%"
Additionally, I'm not fully sure you can use \ as path separator in Unix systems. I suggest you replace it as well:
UPDATE wp_slider
SET path = replace(path, '\\', '/')
WHERE path IS NOT NULL
Update:
What I'm trying to explain is that your procedure is basically correct (except that escaping \ is not always optional):
mysql> CREATE TABLE wp_slider(
-> path VARCHAR(2083)
-> );
Query OK, 0 rows affected (0.06 sec)
mysql> INSERT INTO wp_slider (path) VALUES ('C:\\xampp\\htdocs\\site.com/wp-content/plugins/slider/skins/slider\\circle\\circle.cs
s');
Query OK, 1 row affected (0.04 sec)
mysql> UPDATE wp_slider SET path=REPLACE(path, 'C:\\xampp\\htdocs\\site.com', '/var/www/site.com');
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT * FROM wp_slider;
+----------------------------------------------------------------------------+
| path |
+----------------------------------------------------------------------------+
| /var/www/site.com/wp-content/plugins/slider/skins/slider\circle\circle.css |
+----------------------------------------------------------------------------+
1 row in set (0.00 sec)
If you don't get matches it's because your database contains different data than you think, such as (but not restricted to) whitespace or control characters:
mysql> TRUNCATE TABLE wp_slider;
Query OK, 0 rows affected (0.03 sec)
mysql> INSERT INTO wp_slider (path) VALUES ('C:\xampp\htdocs\site.com/wp-content/plugins/slider/skins/slider\circle\circle.css');
Query OK, 1 row affected (0.02 sec)
mysql> UPDATE wp_slider SET path=REPLACE(path, 'C:\\xampp\\htdocs\\site.com', '/var/www/site.com');
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
mysql> SELECT * FROM wp_slider;
+------------------------------------------------------------------------------+
| path |
+------------------------------------------------------------------------------+
| C:xampphtdocssite.com/wp-content/plugins/slider/skins/slidercirclecircle.css |
+------------------------------------------------------------------------------+
1 row in set (0.00 sec)
In this last example, we forgot to escape \ when inserting and as a result we don't get a match when replacing because the input data is not what we thought it was.
You need to escape the backslashes: \\
Related
I'm trying to update a mariadb table column, to a string that contains a literal backslash.
I want the resulting string in the table to be
4.4 \(blah blah\)
I've tried
UPDATE table SET string = '4.4 \\(blah blah\\)' WHERE string = '4.4 (blah blah)';
This works when I run it in Sequel Pro, but when I run it as part of a ruby/rails migration, the result is that the column remains unchanged, ie. 4.4 (blah blah).
I've tried every combination of single quotes, double quotes, single backslash, double backslash. I also tried a triple backslash.
NO_BACKSLASH_ESCAPES sql_mode.
Enabling this mode disables the use of the backslash character () as
an escape character within strings and identifiers. With this mode
enabled, backslash becomes an ordinary character like any other, and
the default escape sequence for LIKE expressions is changed so that no
escape character is used.
mysql> create table my_table (
-> string varchar(255) );
Query OK, 0 rows affected (0.34 sec)
mysql>
mysql> insert into my_table values
-> ('4.4 (blah blah)');
Query OK, 1 row affected (0.07 sec)
mysql> select ##sql_mode;
+------------------------+
| ##sql_mode |
+------------------------+
| NO_ENGINE_SUBSTITUTION |
+------------------------+
1 row in set (1.318 sec)
mysql> set session sql_mode='NO_BACKSLASH_ESCAPES,NO_ENGINE_SUBSTITUTION';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> UPDATE my_table SET string = '4.4 \(blah blah\)' WHERE string = '4.4 (blah blah)';
Query OK, 1 row affected (0.08 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from my_table;
+-------------------+
| string |
+-------------------+
| 4.4 \(blah blah\) |
+-------------------+
1 row in set (0.02 sec)
I have two tables in a legacy database. One of them contains a field containing some xml. This other table contains the tags that constitutes the xml.
For example consider a table with a list of languages (e.g. en, fr, it) and a table with a field like
<en>Something</en><fr>Quelque chose</fr><it>Qualcosa</it>
I would like to extract all the translations. I have a query that goes like
SELECT GROUP_CONCAT(extractvalue(table.field, languages.sigla))
FROM table, languages
GROUP BY table.id
But I get the following error
[HY000][1105] Only constant XPATH queries are supported
I guess this is a limitation of MySql (I'm usign version 5.6). Is there any other way to obtain what I'm looking for?
One option you can try is (adjust as needed):
mysql> SELECT
-> GROUP_CONCAT('SELECT ExtractValue(#`xml`, \'', `der`.`lang`, '\') `lang`' SEPARATOR ' UNION ALL ') INTO #`query`
-> FROM (
-> SELECT 'en' `lang`
-> UNION
-> SELECT 'fr'
-> UNION
-> SELECT 'it'
-> ) `der`;
Query OK, 1 row affected (0.00 sec)
mysql> SET #`xml` := '<en>Something</en><fr>Quelque chose</fr><it>Qualcosa</it>';
Query OK, 0 rows affected (0.00 sec)
mysql> SET #`query` := CONCAT('SELECT GROUP_CONCAT(`der`.`lang`)
'> FROM (', #`query`, ') `der`');
Query OK, 0 rows affected (0.00 sec)
mysql> PREPARE `stmt` FROM #`query`;
Query OK, 0 rows affected (0.00 sec)
Statement prepared
mysql> EXECUTE `stmt`;
+----------------------------------+
| GROUP_CONCAT(`der`.`lang`) |
+----------------------------------+
| Something,Quelque chose,Qualcosa |
+----------------------------------+
1 row in set (0.00 sec)
mysql> DEALLOCATE PREPARE `stmt`;
Query OK, 0 rows affected (0.00 sec)
I faced the same problem and found an easy workaround in that blog post : http://sql-debug.blogspot.com/2012/05/extractvalue-only-constant-xpath.html
The solution is really surprising, but as silly as it can seem, it works perfectly...
It consists in creating a function that only "wraps" the ExtractValue function, in order to give it the xpath as an already generated string.
delimiter ##
create function exv(xml text, xpath text) returns text charset utf8
begin
return cast(extractvalue(xml, xpath) as char);
end ##
delimiter ;
And then, just replace extractvalue with exv in the query you tried to run when you got this [HY000][1105] error.
Of course, this workaround has a performance cost...
I'm using InnoDb engine by default. And this is what looks strange:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> set session transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)
mysql> create table test_1(id int);
Query OK, 0 rows affected (0.07 sec)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> show tables;
+------------------+
| Tables_in_reestr |
+------------------+
| test_1 |
+------------------+
1 rows in set (0.00 sec)
It looks strange, because I started transaction and rollbacked, but to no avail. So, what I'm doing wrong?
To expand on the comment above: in MySQL, basically all operations that alter database objects perform auto-commit. The main categories are:
any DDL on your objects, like CREATE/ALTER/DROP TABLE/VIEW/INDEX...,
anything that modifies the system database mysql, like ALTER/CREATE USER,
any administrative commands, like ANALYZE,
any data loading/replication statements.
Actually, I find it best to assume that INSERT, UPDATE and DELETE are safe, and anything else is not.
Source: https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html
In the following MySQL code, the first two blocks drop and create a temporary table _temp (with different column labels) and select * from it without a problem. Then, I create a stored procedure that does the same thing (i.e., select * from _temp), and it works first time, but not the second, failing with
ERROR 1054 (42S22): Unknown column 'test._temp.f' in 'field list'
It seems like select * from _temp on its own correctly handles the change in table columns, but the previous columns names are remembered across stored procedure calls. Am I doing something wrong, or is there a workaround?
MySQL Code
drop temporary table if exists _temp;
create temporary table _temp select 'first' as f;
select * from _temp;
drop temporary table if exists _temp;
create temporary table _temp select 'second' as s;
select * from _temp;
drop procedure if exists selectTemp;
create procedure selectTemp()
select * from _temp;
drop temporary table if exists _temp;
create temporary table _temp select 'first' as f;
call selectTemp();
drop temporary table if exists _temp;
create temporary table _temp select 'second' as s;
call selectTemp();
Transcript
$ mysql --version
mysql Ver 14.14 Distrib 5.5.38, for debian-linux-gnu (x86_64) using readline 6.2
mysql> source temp.sql
Query OK, 0 rows affected (0.01 sec)
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
+-------+
| f |
+-------+
| first |
+-------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
+--------+
| s |
+--------+
| second |
+--------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
+-------+
| f |
+-------+
| first |
+-------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
ERROR 1054 (42S22): Unknown column 'test._temp.f' in 'field list'
After paring this down to a minimal working example, and distilling the essential elements, searching for a bug report, this became much easier. It turns out that this was reported all the way back in 2005 as:
Bug #12257 SELECT * inside PROCEDURE gives "Unknown column" on second loop if tbl changed
Some of the bugs marked as a duplicate of that are actually more along the lines of the example:
Bug #15766 select * from table inside stored procedure uses old field names
Bug #49333 Unknown column 'test.TEMPTABLE.column1' in 'field list'
Bug #62406 new cursor, on table with same name but different structure as used before fails
The bug is closed, but apparently not fixed yet, though 5.6 mentions the behavior. From the comments in the bug report:
Noted in 5.6.6 changelog.
"Unknown column" errors or bad data could result from changing the set
of columns in a table used within a stored program between executions
of the program or while the table was used within a program loop.
I am creating my first serious project in PHP and I want to make sure I have my database setup correctly. It is utf8_general_ci and for example the max I want usernames to be is 20 characters, so the username field in the database would be a varchar(20)? Sorry if this is stupid, it is just I read something somewhere that is making me question myself.
Yes you're right:
CREATE DATABASE my_test_db
DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci;
Query OK, 1 row affected (0.00 sec)
USE my_test_db;
Database changed
CREATE TABLE users (username varchar(20));
Query OK, 0 rows affected (0.04 sec)
INSERT INTO users VALUES ('abcdefghijklmnopqrstuvwxyz');
Query OK, 1 row affected, 1 warning (0.00 sec)
SELECT * FROM users;
+----------------------+
| username |
+----------------------+
| abcdefghijklmnopqrst |
+----------------------+
1 row in set (0.00 sec)