I'll start this off by saying I know that there are more practical ways to solve this. It's more of an intellectual curiosity than anything else.
I've inherited a MySQL database where some columns are stored as varchar(5) but actually contain the literals "True" or "False". Changing the structure of the data is not an option right now due to other issues. I'm mapping the columns to an ORM (SQLAlchemy), and I want the column to be mapped to a Boolean data type in the supporting codebase using a type adapter. (I've written this adapter already; it's not the problem.)
To help make the mapping process faster, I'm writing a small query to look at the INFORMATION_SCHEMA table and build a line of Python code defining the column using the ORM's syntax. I cannot assume that the data type varchar(5) is a Boolean column - I need to inspect the contents of that column to see if there are values contained in it besides True and False.
Can I write a query that will both get the column type from INFORMATION_SCHEMA and check the actual values stored in that column?
Here is the query I have so far:
SELECT CONCAT(
"Column(""",
col.column_name,
""", ",
(CASE
WHEN col.DATA_TYPE = "int" THEN "Integer"
-- Code in question
WHEN
col.DATA_TYPE = "varchar"
AND col.CHARACTER_MAXIMUM_LENGTH = 5
AND NOT EXISTS(
-- Doesn't seem to work
SELECT DISTINCT col.COLUMN_NAME
FROM col.TABLE_NAME
WHERE col.COLUMN_NAME NOT IN ("True", "False")
)
THEN "BoolStoredAsVarchar"
WHEN col.DATA_TYPE = "varchar" THEN CONCAT("String(", col.CHARACTER_MAXIMUM_LENGTH, ")")
-- Default if it's not a recognized column type
ELSE col.DATA_TYPE
END),
"),"
) AS alchemy
FROM information_schema.columns AS col
WHERE
col.TABLE_SCHEMA = "my_schema"
AND col.TABLE_NAME = "my_table"
ORDER BY col.ORDINAL_POSITION;
Running this code gives me a permissions error: Error Code: 1142. SELECT command denied to user 'user'#'host' for table 'table_name'. Presumably it's trying to use col.TABLE_NAME as a literal instead of interpreting it.
I've also tried creating a simple stored procedure and making table_name into a variable. However, replacing the FROM clause inside the EXISTS with a variable name gives me a syntax error instead.
Again, it's easy enough to run the query myself to see what's in that column. I'd just like to know if this is possible, and if so, how to do it.
You can't do what you're trying to do in a single query.
The reason is that table names (or any other identifier) must be fixed in the query at the time it is parsed, which is before it has read any values from tables. Thus you can't read the name of a table as a string from information_schema and also read from the table with that name in the same query.
You must read the table name from information_schema and then use that result to format a second query.
This isn't a problem specific to MySQL. It's true of any SQL implementation.
I'm connected to a MySQL server on two different connections. On one of them, I can execute:
query = 'SELECT EXISTS(SELECT * FROM TABLE WHERE COLUMN = "VALUE")'
c.execute(query)
In: c.fetchall()[0][0]
Out: 1
Connected through a second machine, using identical values, I get the following:
query = 'SELECT EXISTS(SELECT * FROM TABLE WHERE COLUMN = "VALUE")'
c.execute(query)
In: c.fetchall()[0][0]
Out: 0
The only thing that seems to fix it is closing the connection and restarting it. It is causing some problems. Is there anything I can do to fix this?
Logically speaking, the same exists query with the same underlying data should return the same result on all machines. However, I see a problem with your query. You are using double quotes around VALUE, which you intend to be a string literal. This could be causing MySQL to view VALUE as an identifier (e.g. as a column). Try using single quotes instead:
query = "SELECT EXISTS (SELECT 1 FROM TABLE WHERE COLUMN = 'VALUE')"
c.execute(query)
In: c.fetchall()[0][0]
I'm currently using the mySQL common schema package along with the split() function, but I'm struggling to get a working JOIN query to work?
set #script := "
split({size:2000} :
UPDATE world
SET world.CountryName = (
SELECT country.nicename
FROM country
WHERE country.iso = world.Country
)
)
{
throttle 4;
SELECT $split_total_rowcount AS 'rows updated so far';
}
";
call common_schema.run(#script);
When running this query, it produces the following:
#1644 - QueryScript error: [split() cannot deduce split table name. Please specify explicitly] at 34: "UPDATE world
SET world.Country
As for why I'm trying to split my UPDATE query into chunks, is because it's trying to update a table that's got 3M+ rows & is struggling when doing the query on it's own
Please specify explicitly appears to refer to using this format:
Multiple tables operations; explicit declaration of splitting table:
split (schema_name.table_name: statement operating on multiple tables)
statement;
https://shlomi-noach.github.io/common_schema/query_script_split.html
See also explicit declaration.
I have an SQL table called "tbl_einheit". phpmyadmin shows more than 14.000 rows in the table. When accessing via webpage, the table is empty "eof".
I minimized the SQL Statment, and deleted all WHERE, ORDER BY elements, so that simply
SELECT * FROM tbl_einheit
is the statement. But it still returns an empty result set. I also tried
SELECT E . * FROM tbl_einheit E, ( SELECT #a := NULL ) AS init LIMIT 0,30
but also empty.
Any suggestions?
the reason is you have some data type in your mysql dtaabse that ADODB connector in ASSp can't recognize, so asp thinks it is EOF.
use CAST in MySQL to convert data type to something asp can understand, example:
SELECT CAST(SUM(Entry_Data_1) as UNSIGNED) as score FROM contests_entries
Put a trace in your code to make sure you are executing the code you think you are.
Double-check your connection string.
I have a MySQL server as a linked server in Microsoft SQL Server 2008. For the link I use MySQL ODBC Connector version 5.1.8. When invoking queries using OPENQUERY (the only way I found of performing queries), problems occur. Simple queries, such as
SELECT * FROM OPENQUERY(MYSQL, 'SHOW TABLES')
work fine. Selection of individual columns, e.g.,
SELECT * FROM OPENQUERY(MYSQL, 'SELECT nr FROM letter')
works fine as well, but SELECT * syntax does not work. The query:
SELECT * FROM OPENQUERY(MYSQL, 'SELECT * FROM mytable')
raises an error:
Msg 7347, Level 16, State 1, Line 6
OLE DB provider 'MSDASQL' for linked
server 'MYSQL' returned data that does
not match expected data length for
column '[MSDASQL].let_nr'. The
(maximum) expected data length is 40,
while the returned data length is 0.
How can I make the SELECT * syntax work?
This problem happens if you are querying a MySQL linked server and the table you query has a datatype char(). This means fixed length and NOT varchar(). This happens when your fixed length field has a shorter string than the maximum length that SQL Server expected to get from the ODBC.
To fix this go to your MySQL server and change the datatype to varchar() leaving the length as it is. Example change char(10) to varchar(10).
Executing the following command before queries seems to help:
DBCC TRACEON(8765)
The error messages go away and queries seem to be working fine.
I'm not sure what it does though; I found it here: http://bugs.mysql.com/bug.php?id=46857
Strangely, SQL Server becomes unstable, stops responding to queries and finally crashes with scary-looking dumps in the logs a few minutes after several queries to the MySQL server. I am not sure if this has to do anything with the DBCC command, so I'm still interested in other possible solutions to this problem.
What I did to fix this since I can't modify the MySQL database structure is just create a view with a cast ex: CAST(call_history.calltype AS CHAR(8)) AS Calltype,
and select my view from MSSQL in my linked server.
The reason behind is that some strange types don't work well with the linked server (in my case the MySQL enum)
I found this
"The problem is that one of the fields
being returned is a blank or NULL CHAR
field. To resolve this in the Mysql
ODBC settings select the option "Pad
CHAR to Full Length"
Look at the last post here
An alternative would be to use the trim() function in your SELECT statement within OPENQUERY. The downside is you have to list each field individually, but what I did was create a view that calls OPENQUERY and then perfrom select * on the view.
Not ideal, but better than changing data types on tables!
Here is a crappy solution I came up with because I am unable to change the datatype to varchar as the db admin for the MySQL server is afraid it will cause issues with his scripts.
in my MySQL select query I run a case statement checking the character length of the string and add a filler character in front of the string "filling it up" to the max (in my case its a char(6)). then in the select statement of the openquery I strip the character back off.
Select replace(gradeid,'0','') as gradeid from openquery(LINKEDTOMYSQL, '
SELECT case when char_length(gradeid) = 0 then concat("000000", gradeID)
when char_length(gradeID) = 1 then concat("00000", gradeID)
when char_length(gradeID) = 2 then concat("0000", gradeID)
when char_length(gradeID) = 3 then concat("000", gradeID)
when char_length(gradeID) = 4 then concat("00", gradeID)
when char_length(gradeID) = 5 then concat("0", gradeID)
else gradeid end as gradeid
FROM sometableofmine')
it works but it probably is slower...
maybe you can make a MySQL function that will do the same logic, or come up with a more elegant solution.
I had the similar problem to this myself, which I resolved by wrapping the column-names in single ` style quotes.
Instead of...
column_name
...use...
`column_name`
Doing this helps the MySql query-engine should the column-name clash with a key or reserved-word.*
Instead of using SELECT * FROM TABLE_NAME, try to use all column names with quotes:
SELECT `column1`, `column2`, ... FROM TABLE_NAME
Example for normal datatype columns
SELECT * FROM OPENQUERY(MYSQL, 'SELECT `column1`, `column2`,...,`columnN` FROM mytable')
Example for ENUM datatype columns
SELECT * FROM OPENQUERY(MYSQL, 'SELECT `column1`, trim(`column2`) `column2`, `column3`,...,`columnN` FROM mytable')
*For those used to Sql Server, it is the MySql equivalent of wrapping a value in square-brackets, [ and ].