通过 Microsoft SQL Server 的 ODBC 在 MySQL 中进行 SELECT * 时出现问题

发布于 2024-10-02 18:53:56 字数 665 浏览 0 评论 0原文

我有一个 MySQL 服务器作为 Microsoft SQL Server 2008 中的链接服务器。对于链接,我使用 MySQL ODBC 连接器版本 5.1.8。当使用OPENQUERY(我发现执行查询的唯一方法)调用查询时,会出现问题。简单的查询,如

SELECT * FROM OPENQUERY(MYSQL, 'SHOW TABLES')

工作正常。例如,选择单个列

SELECT * FROM OPENQUERY(MYSQL, 'SELECT nr FROM letter')

也可以正常工作,但 SELECT * 语法不起作用。查询:

SELECT * FROM OPENQUERY(MYSQL, 'SELECT * FROM mytable')

引发错误:

消息 7347,16 级,状态 1,第 6 行 用于链接的 OLE DB 提供程序“MSDASQL” 服务器“MYSQL”返回的数据确实 与预期数据长度不匹配 列“[MSDASQL].let_nr”。这 (最大)预期数据长度为 40, 而返回的数据长度为0。

如何使 SELECT * 语法起作用?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

零度℉ 2024-10-09 18:53:56

如果您正在查询 MySQL 链接服务器并且您查询的表具有数据类型 char(),则会出现此问题。这意味着固定长度而不是 varchar()。当固定长度字段的字符串比 SQL Server 期望从 ODBC 获取的最大长度短时,就会发生这种情况。

要解决此问题,请转到 MySQL 服务器并将数据类型更改为 varchar() 并保持长度不变。示例将 char(10) 更改为 varchar(10)

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).

落日海湾 2024-10-09 18:53:56

在查询之前执行以下命令似乎有帮助:

DBCC TRACEON(8765)

错误消息消失,查询似乎工作正常。

但我不确定它的作用;我在这里找到它: http://bugs.mysql.com/bug.php?id=46857

奇怪的是,在对 MySQL 服务器进行多次查询后几分钟,SQL Server 变得不稳定,停止响应查询,并最终崩溃,并在日志中出现看起来可怕的转储。我不确定这是否与 DBCC 命令有任何关系,所以我仍然对该问题的其他可能解决方案感兴趣。

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.

流年已逝 2024-10-09 18:53:56

由于我无法修改 MySQL 数据库结构,我所做的解决方法就是创建一个带有强制转换的视图:CAST(call_history.calltype AS CHAR(8)) AS Calltype,
并从我的链接服务器中的 MSSQL 选择我的视图。

背后的原因是一些奇怪的类型不能很好地与链接服务器一起工作(在我的例子中是 MySQL 枚举)

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)

顾挽 2024-10-09 18:53:56

我找到了这个

“问题是其中一个字段
返回的是空白或 NULL CHAR
场地。在Mysql中解决这个问题
ODBC 设置选择选项“Pad
CHAR 到全长”

请参阅此处的最后一篇文章

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

夏见 2024-10-09 18:53:56

另一种方法是在 OPENQUERY 中的 SELECT 语句中使用 trim() 函数。缺点是您必须单独列出每个字段,但我所做的是创建一个调用 OPENQUERY 的视图,然后在视图上执行 select * 。

并不理想,但比更改表上的数据类型要好!

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!

感情旳空白 2024-10-09 18:53:56

这是我想出的一个糟糕的解决方案,因为我无法将数据类型更改为 varchar,因为 MySQL 服务器的数据库管理员担心这会导致他的脚本出现问题。

在我的 MySQL 选择查询中,我运行一个 case 语句检查字符串的字符长度,并在字符串前面添加一个填充字符“填充”到最大值(在我的例子中是 char(6))。然后在 openquery 的 select 语句中,我将字符去掉。

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')

它可以工作,但可能会慢一些...

也许你可以创建一个 MySQL 函数来执行相同的逻辑,或者提出一个更优雅的解决方案。

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.

孤单情人 2024-10-09 18:53:56

我自己也遇到了类似的问题,我通过将列名括在单`样式引号中解决了这个问题。

而不是...

column_name

...使用...

`column_name`

如果列名与键或保留字冲突,这样做有助于 MySql 查询引擎。*

而不是使用 SELECT * FROM TABLE_NAME,尝试使用带引号的所有列名:

SELECT `column1`, `column2`, ... FROM TABLE_NAME

普通数据类型列的示例

SELECT * FROM OPENQUERY(MYSQL, 'SELECT `column1`, `column2`,...,`columnN` FROM mytable')

ENUM 数据类型列的示例

SELECT * FROM OPENQUERY(MYSQL, 'SELECT `column1`, trim(`column2`) `column2`, `column3`,...,`columnN` FROM mytable')

*对于那些用于 Sql Server 的列,它是 MySql 相当于包装值在方括号中,[]

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 ].

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文