问题
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?
回答1:
I was going through the same problem for 4 days but finally I found the why and how to fix it.
This problem happened if you are quering mySQL linked server and the table you query has a datatype char()... This means fixed length NOT varchar(). This happen when your fixed length field has shorter string than the maximum length that sql server expected to get from the odbc.
The fix; go to MySQL server and change the datatype to varchar() leaving the length as it is... Example, char(10) change it to varchar(10).
This will work with no problem.
Please let me know if this fixed it.
Tarek Basta
回答2:
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.
回答3:
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)
回答4:
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
回答5:
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!
回答6:
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.
回答7:
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 ]
.
来源:https://stackoverflow.com/questions/4215979/problem-with-select-in-mysql-through-odbc-from-microsoft-sql-server