Тип данных SQL Server varchar (MAX) в delphi с использованием RemObjects

Получен запрос на изменение максимального размера поля комментария в приложении. Раньше для него было установлено значение varchar (500), поэтому после прочтения документации я решил изменить тип данных поля с varchar (500) на varchar (max ). База данных без проблем принимала изменения (с использованием Microsoft SQL Server Management Studio 2005 и Microsoft SQL Server Management Studio 2008 для управления базой данных). Затем я продолжил менять программное обеспечение. Программное обеспечение написано на Delphi с RemObjects для связи с базой данных. Поэтому я изменил TDASchema для сервера, он сопоставил мое новое поле varchar (max) как тип данных String (65536) (получил Немного беспокоил там такой явный статический размер, но я пошел дальше). Затем я получил схему DataTable для моего объекта TDAMemDataTable, который обновил все поля.

Я запустил приложение и решил посмотреть, примет ли моя база данных изменения в этом конкретном измененном поле. Я отредактировал одну из записей и нажал кнопку, чтобы синхронизировать DataSet с сервером, и получил такое сообщение об ошибке:

Типы данных varchar (max) и текст несовместимы в операторе равенства

Я интерпретирую это как то, что мой объект сервера (тот, который сопоставляет поля базы данных с объектами RemObjects) сопоставил типы данных полей с неправильными типами данных в RemObjects.

Как это можно решить? Какие есть альтернативы?

P.S. В журналах этого выпуска Build .1267 от RemObjects четко указано, что:

исправлено: DataSnap: не удается опубликовать обновления для MSSQL 2005 VARCHAR (MAX)

Я использую версию сборки .1067. Интересно, поможет ли обновление решить проблему

P.P.S. После обновления RemObjects до последней версии проблема сохраняется.


person Boris Mocialov    schedule 01.11.2013    source источник


Ответы (3)


Это сообщение об ошибке обычно возникает при попытке сравнить varchar (n) и текст с помощью оператора равенства (обычно в предложении where в sql, но возможно в другом месте). была статья на MSDN, который охватывает несколько моментов, которые могут иметь к этому отношение.

когда вы сохраняете данные в столбце VARCHAR (N), значения физически сохраняются таким же образом. Но когда вы сохраняете его в столбце VARCHAR (MAX), за экраном данные обрабатываются как ТЕКСТОВОЕ значение. Таким образом, при работе со значением VARCHAR (MAX) требуется дополнительная обработка. (только если размер превышает 8000)

Вы упомянули, что TDASchema сопоставила ваше новое поле как String (65536), которое, хотя никогда раньше не использовало RemObjects, я предполагаю, что где-то в его собственном коде (или вашем) пытается провести какое-то сравнение, отсюда и сообщение об ошибке.

Попробуйте использовать VARCHAR (8000) вместо MAX и посмотрите, решит ли это проблему.

Другой вариант, если вы можете найти, где в коде выполняется проверка равенства, - это попытаться выполнить cast()

person Nick Gulino    schedule 05.11.2013
comment
Я согласен с предложенной вами причиной ошибки, сравнение происходит где-то в библиотеке (возможно, когда какой-то триггер сравнивает старую запись ячейки с новой, где один из них текст, а другой - varchar) Проблема с использованием VARCHAR (8000) в том, что в базе данных будет выделено огромное количество места, чего я не хочу, поскольку свойство MAX выделяет именно то, что необходимо для хранения конкретной переменной varchar. - person Boris Mocialov; 05.11.2013
comment
Да, это проблема. Если вы можете узнать, какие комментарии будут помещены в поле, вы можете хотя бы предположить и уменьшить их размер до приемлемого уровня. - person Nick Gulino; 06.11.2013
comment
Или, может быть, какой-то обработчик исключений, который перехватит исключение и вручную приведет значения? Я никогда раньше не использовал ремобъекты, это единственные идеи, которые у меня есть. - person Nick Gulino; 06.11.2013
comment
Спасибо за ваши идеи, но я бы предпочел дождаться кого-то, кто использовал RemObjects и, возможно, имел аналогичную проблему или может указать мне какое-то направление, если я делаю что-то не так. - person Boris Mocialov; 06.11.2013

Как вы и подозревали, я думаю, что корень ваших проблем в том, что поля не вошли в TDASchema как правильные типы. Я только что попробовал это здесь, и поля varchar (max) и nvarchar (max) попадают в мою схему как Memo и WideMemo соответственно, а не String (65536).

Я использую Delphi XE6 и SQL Server 2008 R2 через FireDAC.

Это наводит на мысль о проблеме с получением метаданных из базы данных. Какой драйвер базы данных вы используете? Можете ли вы попробовать FireDAC (если есть) или другой драйвер, чтобы увидеть, сохраняется ли проблема?

person Toby Groves    schedule 18.08.2014

Решение для Delphi 7 и MS SQL Server 2008 R2 (SP2)

Delphi:

    with TADOStoredProc.Create(Self) do
    try
      Connection := AConnection;
      ProcedureName := ASPName;
      Parameters.Refresh;
      Parameters.ParamByName('@XML').Value := AXML;
      try
        ExecProc;
...

Сервер MS SQL:

ALTER PROCEDURE dbo.StoredProcName
    @XML        NVARCHAR(MAX)
   ,@ErrMsgOut  NVARCHAR(MAX) = NULL OUT
AS BEGIN
SET NOCOUNT ON
DECLARE @RETURN INT = 0
       ,@idoc   INT

BEGIN TRY
    -- Prepare XML
    DECLARE @XML_TEXT VARCHAR(MAX)
    SET @XML_TEXT = CONVERT(VARCHAR(MAX), @XML) 
    EXEC sp_xml_preparedocument @idoc OUTPUT, @XML_TEXT

    -- Open XML
    SELECT  *
    FROM    OPENXML (@idoc, '/ServicesList/ServicesItem', 2)
    WITH
    (
        YourFields AndTypes
    )
...
person ssv555    schedule 18.09.2015