Невозможно вставить Unicode в SQL Server 2008, используя Delphi ZeosLib и Delphi 7

У меня возникают проблемы при вставке Unicode в базу данных SQL Server с использованием Delphi ZeosLib и Delphi 7, а затем при чтении вставленного значения. Я создал простую тестовую программу, которая сначала вставляет, а затем запрашивает вставленное значение.

Схема тестовой таблицы:

CREATE TABLE [dbo].[incominglog](
    [message] [nvarchar](500) NULL
) ON [PRIMARY]

Я загрузил простой источник тестовой программы (включая исходный код ZeosLib) - нажмите здесь, чтобы загрузить. Я также включил ntwdblib.dll, но вы можете использовать свой собственный.

Для тестовой программы также требуется компонент TNT, который можно скачать здесь

Используя тестовую программу, символы Unicode, которые я вставил, отображаются в виде вопросительных знаков при извлечении - я не уверен, связана ли проблема с кодом вставки или кодом запроса.

Я также пытался кодировать данные в utf-8 перед вставкой, а затем декодировать данные после извлечения из utf-8 - пожалуйста, найдите "// вставлен как utf8" в исходном тексте тестовой программы. Я могу просматривать Unicode после того, как он был декодирован, поэтому этот метод работает. Однако для моего реального приложения я не могу кодировать как UTF-8, так как SQL Server не полностью поддерживает UTF-8 - некоторые символы не могут быть сохранены. Смотрите мой предыдущий вопрос здесь.

Буду признателен за любые указатели.:)

Между тем, вот источник для тестовой программы:

unit Unit1;

interface

uses
  ZConnection, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ZAbstractRODataset, ZAbstractDataset, ZAbstractTable, ZDataset,
  StdCtrls, TntStdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    TntMemo1: TTntMemo;
    Button2: TButton;
    TntEdit1: TTntEdit;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  FZConnection: TZConnection;
  FZQuery: TZQuery;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  tntmemo1.Lines.Clear;
  FZConnection := TZConnection.Create(Owner);
  FZConnection.LoginPrompt := False;
  FZQuery := TZQuery.Create(Owner);
  FZQuery.Connection := FZConnection;
  FZConnection.Protocol := 'mssql';
  FZConnection.Database := 'replace-with-your-db';
  FZConnection.HostName := 'localhost';
  FZConnection.User := 'sa';
  FZConnection.Password := 'replace-with-your-password';
  FZConnection.Connect;
  FZQuery.SQL.Text := 'SELECT * from incominglog';
  FZQuery.ExecSQL;
  FZQuery.Open;
  FZQuery.First;
  while not FZQuery.EOF do
  begin
   tntmemo1.Lines.add(FZQuery.FieldByName('message').AsString);
  // tntmemo1.Lines.add(utf8decode(FZQuery.FieldByName('message').AsString));  //inserted as utf8
    FZQuery.Next;
  end;

end;

procedure TForm1.Button2Click(Sender: TObject);
var
sqlstring, data:widestring;
begin
  FZConnection := TZConnection.Create(Owner);
  FZConnection.LoginPrompt := False;
  FZQuery := TZQuery.Create(Owner);
  FZQuery.Connection := FZConnection;
  FZConnection.Protocol := 'mssql';
  FZConnection.Database := 'replace-with-your-db';
  FZConnection.HostName := 'localhost';
  FZConnection.User := 'sa';
  FZConnection.Password := 'replace-with-your-password';
  FZConnection.Connect;
  data:= tntedit1.Text;
 // data:= utf8encode(tntedit1.Text);  //inserted as utf8
  sqlstring:= 'INSERT INTO INCOMINGLOG ([MESSAGE]) VALUES(N''' + data + ''')';
  FZQuery.SQL.Text := sqlstring;
  FZQuery.ExecSQL;
end;

end.

1 ответ

Я не проверял ваш пример, но я могу без проблем сохранять и извлекать из базы данных символы Юникода на SQL Server с Delphi 7 VCL/CLX и zeoslib.

Я думаю, что в вашем случае будет достаточно изменить процедуру сохранения следующим образом:

procedure TForm1.Button2Click(Sender: TObject);
var
sqlstring : widestring;
data : UTF8String;
begin
  FZConnection := TZConnection.Create(Owner);
  FZConnection.LoginPrompt := False;
  FZQuery := TZQuery.Create(Owner);
  FZQuery.Connection := FZConnection;
  FZConnection.Protocol := 'mssql';
  FZConnection.Database := 'replace-with-your-db';
  FZConnection.HostName := 'localhost';
  FZConnection.User := 'sa';
  FZConnection.Password := 'replace-with-your-password';
  FZConnection.Connect;
  data:= UTF8String( utf8encode(tntedit1.Text) );
  sqlstring:= 'INSERT INTO INCOMINGLOG ([MESSAGE]) VALUES(:DATA)';
  FZQuery.SQL.Text := sqlstring;
  FZQuery.ParamByName('DATA').AsString := data;
  FZQuery.ExecSQL;
end;

Смысл в том, чтобы изменить строковую переменную данных в типе UTF8String и использовать параметры для передачи строки данных в запрос... Честно говоря, я использую ее с командами ZTable и Post, но она должна быть такой же, как и у ZQuery, как у вас...

Другие вопросы по тегам