I have a series of tables with the same prefix, and I need to select data from the latest version --whose postfix with the highest numeric number. Here is what I have:
SELECT
#latest_version_number :=
MAX(
CAST(SUBSTRING_INDEX(table_name,'_',-1) AS UNSIGNED)
)
FROM information_schema.tables
WHERE lower(table_name) like '{table_prefix}%';
SELECT
*
FROM CONCAT('`{table_prefix}', CAST(#latest_version_number AS CHAR), '`')
It behaved like what I expected when ran as 2 separate queries in the console. But I got "syntax error" trying to run it as a single query. What's the cleanest way to refactor this into a single query? Thanks
The only way I'm aware that you can use a variable in a table name in MySQL is using the prepare + execute statements.
Here is an example I found online that gives you exact instructions.
https://www.tutorialspoint.com/set-user-defined-variable-with-table-name-in-mysql-prepare-statement
Related
Background:
I am working on a project which generates documents based on the contents of a remote MySQL (v8) database . To accomplish this, the program uses a local MSSQL (2017) database with a link to the remote MySQL db.
Issue:
I need to update the MySQL database based the contents of a query from the MSSQL as follows:
EXEC('UPDATE LinkedMySQLDB.TableToUpdate AS a SET a.MySQLField=''updated'' WHERE a.ID IN (LocalMSSQLDB.LocalTable.ID) ;') AT LinkedMySQLServer
However, every time I try this it throws an error at:
(LocalMSSQLDB.LocalTable.ID)
Question:
Is there a way to pass the results of a local query into the query string for the remote database?
Or, is there a different approach that is recommended?
Thanks in advance.
You are trying to access the values of LocalMSSQLDB.LocalTable.ID on MySQL server. That is not possible.
You could use a variable to calculate the statement.
In the example below I use some other names for the databases and fields. But you should get the general idea. By using concat I combine text parts with the result of the subqueries converted to a comma separated list using STRING_AGG.
declare #strSQL varchar(200);
select #strSQL=concat('UPDATE test.test set text=''updated'' WHERE ID in (',(SELECT STRING_AGG(ID, N', ') FROM [SQLTest].dbo.tblTest),');');
EXEC(#strSQL) AT MYSQL2;
This part (SELECT STRING_AGG(ID, N', ') FROM [SQLTest].dbo.tblTest) returns a string. If the local table contains the ID's 1 and 2, the result will be 1, 2. Concatenated with 'UPDATE test.test set text=''updated'' WHERE ID in (' and ');' the final result will be:
UPDATE test.test set text='updated' WHERE ID in (1, 2);
When this is send to the MySQL server named MYSQL2, you get the desired result.
On your servers it would be something like:
declare #strSQL varchar(200);
select #strSQL=concat('LinkedMySQLDB.TableToUpdate AS a SET a.MySQLField=''updated'' WHERE ID in (',(SELECT STRING_AGG(ID, N', ') FROM LocalMSSQLDB..LocalTable),');');
EXEC(#strSQL) AT LinkedMySQLServer;
Be sure to make room for all your id's in #strSQL. 200 characters might not be enough.
I am trying to finish one task little bit faster and I have two problems (hopefully possible to include in one question because both problems would appear in one query).
I would like to use result of one SQL query (which is multiple id's) as table names for another query (FROM ...? ).
Then final results (for each table) should be written in multiple .csv OUTFILE's instead of one that I have at the moment.
I have two queries ready, but I think Its not important for this question and this is why I skipped to post anything.
You may give me example on the simplest SELECT query.
You can use server-side prepared statements:
https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
Here is an example that is hopefully helpful:
select #q:=concat("select count(*) from ", tbl_name)
from my_db.my_tables where table_id = 3;
prepare s from #q;
execute s;
results in executing select count(*) from whatever the value of tbl_name was in my_db.my_tables for the table_id equal to 3.
To export the result to CSV you can do:
select #q:=concat("select count(*) from ", tbl_name,
" into outfile '/tmp/data.csv' fields terminated by ','")
from my_db.my_tables where table_id = 3;
To learn more about SELECT ... INTO OUTFILE:
https://dev.mysql.com/doc/refman/5.7/en/select-into.html
Previously I was using the MySQL. With that I was able to use the query below to get the maximum number from the database.
Here 'No' is the varchar(10):
SELECT max(cast(No as unsigned)) as No FROM `tableName` LIMIT 1
The above query working fine in MySQL. I want to do the same thing in the MS SQL. When I run the same query, I get the following error:
Warning: sqlsrv_fetch_array() expects parameter 1 to be resource, boolean given
Any advice on this?
There is no LIMIT in SQL Server, no unsigned datatype, and no need to quote the table name.
Does this work:
SELECT max(cast(No as bigint)) as No FROM tableName
I have a problem with Aliased Columns in MySQL!
My Query:
SELECT Price AS Pr, (Pr*10/100) FROM MyTable;
MySQL WorkBench Error: UnKnown Column 'Pr' in Field List !!!
I tested my query in W3Schools with no error !
I tested my query in W3Schools with no error!
This doesn't prove that your query is valid.
You can only use aliases in GROUP BY, ORDER BY or HAVING clauses. Your usage variant is not allowed, because the value of alias is not known when MySQL is selecting the 2-nd column.
I've got a suspicion that W3Schools uses MS Access to run user queries, and MS Access does allow such atrocity as referencing column aliases in a SELECT clause that are defined in the same SELECT clause.
The standard doesn't allow this and MySQL does follow standard in this particular case.
As for solution to your problem, I can see two options.
The more generic solution, which would run in probably any SQL product, would be to use a derived table:
SELECT
Pr,
(Pr * 10 / 100) AS SomethingElse
FROM
(
SELECT
SomeComplexExpression AS Pr
FROM MyTable
) AS sub
;
The other option would be to use a variable, which is MySQL-specific:
SELECT
#Pr := SomeComplexExpression AS Pr,
(#Pr * 10 / 100) AS SomethingElse
FROM MyTable
;
Finally, if you need to test/demonstrate if something can/cannot work in MySQL, I'd recommend using SQL Fiddle.
Trying to get a check sum of results of a SELECT statement, tried this
SELECT sum(crc32(column_one))
FROM database.table;
Which worked, but this did not work:
SELECT CONCAT(sum(crc32(column_one)),sum(crc32(column_two)))
FROM database.table;
Open to suggestions, main idea is to get a valid checksum for the SUM of the results of rows and columns from a SELECT statement.
The problem is that CONCAT and SUM are not compatible in this format.
CONCAT is designed to run once per row in your result set on the arguments as defined by that row.
SUM is an aggregate function, designed to run on a full result set.
CRC32 is of the same class of functions as CONCAT.
So, you've got functions nested in a way that just don't play nicely together.
You could try:
SELECT CONCAT(
(SELECT sum(crc32(column_one)) FROM database.table),
(SELECT sum(crc32(column_two)) FROM database.table)
);
or
SELECT sum(crc32(column_one)), sum(crc32(column_two))
FROM database.table;
and concatenate them with your client language.
SELECT SUM(CRC32(CONCAT(column_one, column_two)))
FROM database.table;
or
SELECT SUM(CRC32(column_one) + CRC32(column_two))
FROM database.table;