In my windows machine when I select table names from mysql using the following query I'm getting table names as case sensitive.
mysql> select table_schema, table_name
from information_schema.tables where table_schema='test';
+--------------+------------+
| table_schema | table_name |
+--------------+------------+
| test | TableOne |
| test | TableTwo |
+--------------+------------+
2 rows in set (0.00 sec)
But when I select by table name i'm getting different result.
mysql> select table_schema, table_name from information_schema.tables
where table_schema='test' and table_name = 'TableOne';
+--------------+------------+
| table_schema | table_name |
+--------------+------------+
| test | tableone |
+--------------+------------+
1 row in set (0.00 sec)
What made it even stranger is this.
mysql> select table_schema, table_name from information_schema.tables
where table_schema='test' and table_name like 'TableOne';
+--------------+------------+
| table_schema | table_name |
+--------------+------------+
| test | TableOne |
+--------------+------------+
1 row in set (0.00 sec)
There is a MySql variable called lower_case_table_names. When this is set to 0 table names are case sensitive. But this is not advised on a case insensitive machine like windows. The next option is 1. In this option all table names are converted to lower case even before it is stored. You'll always get lower case table names in this case. In my case the value of this variable is set to 2. And in this case MySql stores table names as such, but when we compare table names, it'll convert them to lower case and compare.
So In the first case table name is not compared, hence we get the original value.
In the second case we are comparing the table name, so mysql convert table name to lower case for comparison. But strangely they are returning the converted value, not the original.
And finally in the third case we are using like operator which itself is case insensitive, hence mysql doesn't bother to convert table name to lower case, and we get the original result.
Related
Based on https://stackoverflow.com/a/59666211/4250302 I created the stored function get_enum_item for future processing the lists of possible values in the ENUM() type fields.
It works fine enough, but... but I can't determine what to do if the delimiter itself is the part of a string being split. For example:
(square brackets are for readability)
mysql> set #q=",v1,',v2'" --empty string, "v1", "comma-v2";
mysql> select concat('[',get_enum_item(#q,',',0),']') as item;
+------+
| item |
+------+
| [] |
+------+
it is OK
mysql> select concat('[',get_enum_item(#q,',',1),']') as item;
+------+
| item |
+------+
| [v1] |
+------+
it is also OK
mysql> select concat('[',get_enum_item(#q,',',2),']') as item;
+------+
| item |
+------+
| ['] |
+------+
It is not OK
the #q contains 3 commas, the first two of these are real delimiters, while the last one is the part of the third possible value: "comma-v-two". And I have no idea how to avoid confusion of splitting function. MySQL WorkBench in the "form editor" mode solves this trouble somehow, but how can I solve this with MySQL's code?
Well, I can rely on the fact that the show_columns-like queries show the enums in "hardcoded" manner:
select column_name,column_type
from information_schema.columns
where data_type='enum' and table_name='assemblies';
+--------------+------------------------------------------------------------------+
| COLUMN_NAME | COLUMN_TYPE |
+--------------+------------------------------------------------------------------+
| AssetTagType | enum('','И/Н','Н/Н',',fgg') |
| PCTagType | enum('','И/Н','Н/Н') |
| MonTagType | enum('','И/Н','Н/Н') |
| UPSTagType | enum('','И/Н','Н/Н') |
| OtherTagType | enum('','И/Н','Н/Н') |
| state | enum('в работе','на списание','списано') |
+--------------+------------------------------------------------------------------+
Thus I can try to use ',' as a delimiter, but this will not save me from the case if the "comma-apostrophe" combination is the part of possible value... :-(
The only thing I can imagine is to count apostrophes and if the delimiting comma is after the even number of ''s, then it is the delimiter, while if it follows an odd number of ''s, it is the part of the value.
And I can't invent anything except for dumb scanning the input string inside the loop. But maybe there are some other suggestions to get the values split correctly?
Please, don't suggest use PHP, Python, AWK, and so on. The query will be executed from the Pascal (Lazarus, CodeTyphoon) application, and calling external processors is highly unsafe.
As a last resort, I can process the column_type with Pascal's code, but at first, I must make myself sure that the task is not solvable by MySQL's features.
edit:
select column_type from information_schema.columns
where column_name='assettagtype' and table_name='assemblies';
+------------------------------------------+
| COLUMN_TYPE |
+------------------------------------------+
| enum('','И/Н','Н/Н',''''',fgg','''') |
+------------------------------------------+
1 row in set (0.00 sec)
Fourth field: '',fgg, fifth field: '
set #q="'в работе','на списание','списано'";
WITH RECURSIVE cte as (
select 1 as a union all
select a+1 from cte where a<35
)
select distinct regexp_substr(#q,'''[^,]*''',a) as E from cte;
Too high values for 35 raise an error ERROR 3686 (HY000): Index out of bounds in regular expression search.. (I created a bug for this)
The null value should be filtered out... 😉
output:
E
'в работе'
'на списание'
'списано'
null
EDIT: With some effort, this also works for a more complex example (not for every "staged" example!)
set #q="'в работе','на списание','списано',''',fgg'";
select #q;
WITH RECURSIVE cte as (
select 1 as a union all
select a+1 from cte where a<35
)
select distinct regexp_substr(#q,'(''([^,]|[^''][^''])*'')',a) E from cte;
output:
E
'в работе'
'на списание'
'списано'
''',fgg'
I want to find all tables and views created before a certain timestamp. For tables it is easy, just
SELECT * FROM information_schema.tables
WHERE table_type = 'TABLE' AND create_time < :ts
But for views it is not so simple. The create_time column is null for all the views in information_chema.tables. e.g.
MariaDB [MYDB]> SELECT IF(create_time IS NULL, 'Null', 'Not Null') AS has_create_ts
, COUNT(1)
FROM information_schema.tables
WHERE table_type = 'VIEW' GROUP BY has_create_ts;
+---------------+----------+
| has_create_ts | COUNT(1) |
+---------------+----------+
| Null | 70 |
+---------------+----------+
1 row in set, 10 warnings (0.371 sec)
And the information_schema.views table does not have any timestamp columns.
So how can I find out when a view was created? Or is it just not possible.
If it matters database version is:
MariaDB [MYDB]> SELECT VERSION();
+--------------------+
| VERSION() |
+--------------------+
| 10.3.7-MariaDB-log |
+--------------------+
1 row in set (0.392 sec)
So how can I find out when a view was created? Or is it just not possible.
No, this is not possible.
A view does not actually contains data, it just made of a definition, ie a SQL statement that references data contained in real (physical) tables : hence this is all that INFORMATION_SCHEMA.VIEWS can show you.
I have mysql table with multiple columns, a column has string data type namely code and the values of the column might be digits only or mixed of string and digits e.g: one row value has 57677 and other rows column value like 2cskjf893 or 78732sdjfh.
mysql> select * from testuser;
+------+--------------+
| id | code |
+------+--------------+
| 1 | 232 |
| 2 | adfksa121dfk |
| 3 | 12sdf |
| 4 | dasd231 |
| 5 | 897 |
+------+--------------+
5 rows in set (0.00 sec)
mysql> show create table testuser;
+----------+------------------------------------------------------------------ ---------------------------------------------------------------+
| Table | Create Table |
+----------+------------------------------------------------------------------ ---------------------------------------------------------------+
| testuser | CREATE TABLE `testuser` (
`id` int(11) DEFAULT NULL,
`code` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+----------+------------------------------------------------------------------ ---------------------------------------------------------------+
1 row in set (0.00 sec)
mysql>
I would like to filter out only rows which has numeric value in code column or filter rows which has string values in code column.
try this
Mysql Query to fetch only integer values from a particular column
SELECT column FROM TABLE where column NOT REGEXP '^[0-9]+$' ;
Mysql Query to fetch only string values from a particular column
SELECT column FROM TABLE where column REGEXP '^[0-9]+$' ;
To get digits
SELECT id,code
FROM table_name
WHERE code REGEXP '^[0-9]+$';
To get string values
SELECT *
FROM table_name
WHERE code REGEXP '^[a-zA-Z]+$'
Use regular expressions
SELECT *
FROM myTable
WHERE code REGEXP '^[0-9]+$';
This will filter out column values with all digits.
You can use regular expressions in mysql too.
SELECT * FROM `table` WHERE `code` REGEXP '[0-9]';
Results will be the rows, where any number in the code column.
Try this,
select id,code from table_name where code NOT REGEXP '^[0-9]+$'
Or,
select id,code from table_name where code like '%[^0-9]%'
Using purely MySQL, I want to search and replace 'oldString' with 'newString' from and undetermined number of tables and columns. A search for my table prefix in information_schema, reveals all the tables that I need to look for.
I have the following trials:
Querying DB table prefix on information_schema
SELECT TABLE_SCHEMA, TABLE_NAME
FROM information_schema.TABLES WHERE table_name LIKE '%mysite_www%'
Results:
+-----------------+----------------------------+
| TABLE_SCHEMA | TABLE_NAME |
+-----------------+----------------------------+
| myDB | mysite_www_moredata |
| myDB | mysite_www_data |
| myDB | mysite_www_urls |
| myDB | mysite_www_pages |
| myDB | mysite_www_feedback |
| myDB | mysite_www_comments |
| myDB | mysite_www_links |
+-----------------+----------------------------+
Query results yields about 200 tables or so.
I want to take the results, filter it for a particular string and replace it with a new one. Replace 'oldString' with 'newString'.
For each TABLE_NAME, search for any column WHERE column LIKE '%oldString%'.
WHERE CONCAT(table1, table2, ... tableN) LIKE 'oldString';
For each column result, update 'oldString' to 'newString'.
UPDATE tableN SET columnN = REPLACE (columnN, '%oldString%', 'newString') WHERE URL LIKE '%oldString%';
I need to do this in pure MySQL as it will be a store procedure. Any assistance or tips is greatly appreciated.
So by using information_Schema you can query both the tables and columns to get a result. I have done something similar in this SO answer.
Essentially query the information_schema and let MySQL construct the SQL for you. The above link should get you going.
UPDATE:
You can use the following query to construct all the Update statements
SELECT CONCAT('UPDATE ',TABLENAME, 'SET ', COLUMN_NAME,'= REPLACE (',COLUMN_NAME, '''%oldString%'', ''newString'') WHERE URL LIKE ''%oldString%''')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE '%somecriteria%' AND COLUMN_NAME LIKE '%somecriteria%'
Insert these resulting string into a temp table then loop through the rows executing the string by using the technique described here
I have a list of strings, and I'd like to see only the ones that are not in the database.
For example I have this string: "Conducteur(trice) de bus" that is in the database:
So if I do something like:
mysql> select * from job where description = "Conducteur(trice) de bus";
+-------+--------------------------+
| id | description |
+-------+--------------------------+
| 14495 | Conducteur(trice) de bus |
+-------+--------------------------+
1 row in set (0.00 sec)
mysql>
Now if the job "Cinéaste" doesn't exist:
mysql> select * from job where description = "Cinéaste";
Empty set (0.00 sec)
mysql>
But I want the exact opposite, i.e. if the string is here I don't want a result to show up, and if it's not here, I'd like the string to show up.
Here's what I'd like for the same strings explained before:
mysql> select * from job [clause i don't know] "Conducteur(trice) de bus";
Empty set (0.00 sec)
mysql>
mysql> select * from job [clause i don't know] "Cinéaste";
+-------------+
| description |
+-------------+
| Cinéaste |
+-------------+
mysql>
So when the record is found, nothing is shown, and when it's not found, the string I was looking for is shown.
Any idea how I could do such queries with MySQL?
Edit: Try
SELECT 'Cinéaste' AS 'description' FROM `job` WHERE NOT EXISTS
(SELECT * FROM `job` WHERE description = 'Cinéaste')
LIMIT 1
You should create a table (can be a temporary table) with the list of strings to check, one per row. Let's consider you create a table named check, with a column description containing the values to be checked. Then you could use this query:
SELECT description
FROM check
WHERE description NOT IN (
SELECT DISTINCT description FROM metier
);