从寻址链接Oracle服务器的SQL Server存储过程返回的无效数据(????)

本文关键字:无效 返回 存储过程 数据 Server 链接 寻址 Oracle 服务器 SQL | 更新日期: 2023-09-27 18:26:58

我们有以下场景:过程是在输出时使用Oracle存储过程返回带有希腊字母的字符串。

Oracle函数(示例)为:

FUNCTION GREEKLATINSTRING (a_latin_name IN VARCHAR2) RETURN VARCHAR2
 IS
 BEGIN RETURN 'ΣΤΡΟΒΟΛΟΣ/123/ABC'; END;

该函数是从T-SQL存储过程中调用的(请假设所有连接都是100%的,因为我们有其他过程在执行时没有问题)

TSQL存储过程是:

CREATE PROCEDURE [dbo].[GreekLatinString] @NameLatin NVARCHAR(100)
AS 
    DECLARE @output NVARCHAR(100);
    DECLARE @SQL NVARCHAR(MAX);
BEGIN
    SET @SQL = N'BEGIN ? := LINKED_SERVER.DB_INSTANCE.GREEKLATINSTRING(?); END;';
    EXECUTE(@SQL, 
            @output            OUTPUT    ,
            @NameGr                      ) --1Params
            AT MYORACLE;
    SELECT cast (@output as nvarchar)
END

C#代码并没有什么特别之处——只是简单地获取数据:

dbCommand = CreateCommand();
dbCommand.Transaction = ModelContext.CurrentDBUtils.Transaction;
dbCommand.CommandText = "GreekLatinString";
dbCommand.CommandType = CommandType.StoredProcedure;
SqlParameter param0 = new SqlParameter("NameLatin", nameLatin);
param0.Direction = ParameterDirection.Input;
dbCommand.Parameters.Add(param0);
using (SqlDataAdapter adapter = new SqlDataAdapter(dbCommand as SqlCommand))
{
   adapter.Fill(dataset);
}

SQL Server实例排序规则为SQL_Latin1_General_CP1253_CI_AS,Oracle NLS_LANGal32utf8

问题是,每当函数在Oracle中直接执行时,它都会返回它应该返回的值,然而,每当我们从SQL Server存储过程内部的C#调用时,数据集中的输出总是????????

有人能提出这可能是什么原因吗?

从寻址链接Oracle服务器的SQL Server存储过程返回的无效数据(????)

不是一个真正的答案,但时间太长,无法发表评论:

当Oracle数据库和Oracle客户端的字符集不同时,Oracle将在两个方向上执行字符数据的转换。如果目标字符集不支持源字符,Oracle将替换一些有效的字符。在许多单字节字符集中,某些东西是?,在Unicode字符集中,使用u+FFFD,REPLACEMENT CHARACTER

请注意,客户端字符集对于客户端机器是不固定的,但可以在连接级别设置

在这种情况下:

  1. 字符数据来源于Oracle数据库字符集。该字符数据包括希腊字母
  2. 字符数据被发送到SQL Server的链接数据库连接所使用的Oracle客户端。如果客户端字符集和数据库字符集不同,则会发生转换
  3. 从Oracle客户端,字符数据可以通过其他软件层传输。(例如OLE DB。)
  4. 字符数据被带入SQL Server
  5. 将显示字符数据。希腊字母成了问号

我的猜测是,第2步中的Oracle客户端字符集是一个不支持希腊字母的单字节字符集,在这一步中,字符被转换为问号。这就是我开始调查的地方。同样,客户端字符集不是为机器设置的,因此不能在SQL Server机器上启动SQLPlus并说"行,问题不在Oracle客户端字符集中。"因为SQLPlus可能使用了与SQL Server不同的东西。

一旦您验证了Oracle客户端字符集是合适的,并且如果您仍然有问题,您就必须找出如何继续工作。我没有任何指导。也许可以针对您正在使用的相同OLE DB驱动程序编写一个简单的客户端应用程序。我不确定。