Обрезка ответа на sql-запрос

    UPDATE!

    Проблема решена после внимательного изучения документации по формату idc. Длина колонки в нем по умолчанию равна 8192 байта, а все что меньше просто обрезается. Прямо так и написано. Для вывода информации свыше этого есть специальный ключ MaxFieldSize, значением которого является максимальная длина ответа в байтах. Приведу цитату, может кому пригодится:
    The MaxFieldSize field specifies the maximum number of bytes allocated by the IDC for each field in the .idc file.
    --------------------------------------------------------------------------------
    NOTE: The default field size is 8,192 bytes. If a query results in more bytes than allocated by the IDC MaxFieldSize field, subsequent data is truncated.
    --------------------------------------------------------------------------------
    To specify a MaxFieldSize of 64,000 bytes, use the following syntax in the MaxFieldSize field entry:
    MaxFieldSize: 64000


    UPDATE!

    Дорогой Хабрахабр, я пришел спросить твоего совета. Перерыл все что только можно и не могу найти решения.
    Имеет место следующая проблема:
    На MS SQL 2000 сервере есть база данных, в которой есть таблица, в которой есть столбец типа text. В нем хранятся данные (новости), которые надо постоянно показывать. Пользователь вызывает скрипт, которой обрабатывает IIS.
    Скрипт состоит из двух файлов — script.idc и template.htx. Это старая технология, позволяющая разделить запрос к БД и шаблон оформления, в котором результат запроса выдается.
    Содержимое script.idc:
    DataSource: sqlserv_tcp
    Username: user1
    Password: pass1
    Template: template.htx
    SQLStatement:
    +SELECT mes_text ne_text FROM news_text (nolock) WHERE mes_id = '%mes_id%' and source_code = 'Source1'


    Содержимое template.htx:
    <%begindetail%><%ne_text%>
    <%enddetail%>


    К этому скрипту обращается программа-клиент под винду.
    Суть проблемы — отрезаются данные свыше 8 килобайт. Это не зависит от клиента, т.к. при открытии URL через браузер все точно также. Перепроверили все. Сервер отдает данные полностью. Грешим на внутренние ограничения ODBC или технологии IDC-файлов, но ничего подобного в мануалах и документации я не нашел. Причем, имеется возможность задавать ключ в файле:
    ODBCOptions: SQL_MAX_LENGTH= Integer,
    задающий максимальную длину в байтах, возращаемых в ответе на запрос, который как ни странно не работает.

    Пока что я решил проблему созданием двойного запроса, но он не универсален и работает только для новостей менее 16 кб, что неприемлемо. Вот он, запрос:
    DECLARE @len int
    SELECT @len=DATALENGTH(mes_text) FROM news_text (nolock) WHERE mes_id = '%mes_id%' AND source_code = Source1'
    IF @len > 6000
    BEGIN
    SELECT SUBSTRING(mes_text,1,6000) ne_text, 1 sort FROM news_text (nolock) WHERE mes_id = '%mes_id%' AND source_code = 'Source1'
    UNION
    SELECT SUBSTRING(mes_text,6001,DATALENGTH(mes_text)) ne_text2, 2 sort FROM news_text (nolock) WHERE mes_id = '%mes_id%' AND source_code = 'Source1'
    ORDER BY sort
    END
    ELSE
    SELECT mes_text ne_text FROM news_text (nolock) WHERE mes_id = '%mes_id%' AND source_code = 'Source1'


    Может кто сталкивался, или есть идеи? Уже несколько дней бьюсь головой в монитор… :)

    Комментарии 36

      0
      ха-хабра-кат ;)

      > Уже несколько дней бьюсь головой в монитор… :)
      это помогает? ;)
        0
        Сделал кат. Не помогает, голова болит. :)
          0
          позвоните в мяу-крософт ;)
            0
            Звонок с вопросом по поводу SQL Server 2000 Enterprise стоит у них 170 баксов. ;)
        –12
        Помогать друг другу нужно! Но это не форум.
          0
          На форумах уже спрашивал, уже на двух. И везде молчат.
          0
          MS SQL не знаю, но вот тут что-то про 8Кб и бинарные типы данных пишут.
          www.basenow.com/help/Data_types_in_Microsoft_SQL_Server.asp
            0
            Это они про varchar(8000) пишут. Там text, с которым работать сплошной геморрой…
              0
              Да, точно
                0
                Ой, отправилось уже
                Там еще про ntext какой то пишут.
                  0
                  Вроде, там все еще хуже ))
                  0
                  В 2005 вроде 2Гб.
                    0
                    Да, в 2005-м поле text может содержать данные до 2-х гб. Мало того, там еще есть varchar(max), аналогичный по сути. У нас стоит 2000 версия, в которой нет varchar(max), а поле text является таким же. Но это все хорошо, главное, что ответ возвращаемый пользователю не содержит всего того, что есть в БД.
                      0
                      Если я правильно понял, то в 2000 и сохранено может быть в одном текстовом поле макс. 8к данных? Если да, то по идее больше вернуть и не получится.

                      Taк же я прочитал (возможно не очень внимательно, потому может быть неверно), что данные передаются кусками маx. 8k? Если это верно, может запрос надо как то особо обрабатывать?
                        0
                        Можно сохранить больше 8 кб, если использовать поле типа text. С ним и напряги.
                        Насчет какой-то другой обработки запроса не знаю, никогда не слышал…
                0
                А Вы уверены, что Ваши данные хранятся на сервере?
                Что показывает текущее выполнение запроса в EM?
                  0
                  Конечно уверен, смотрел на них из студии. В базе все правильно.
                  Что такое ЕМ?
                    0
                    EM = Enterprise Manager. Короче, я так студию назвал по привычке, это старое название.
                    Навскидку ничего не вспоминается из подобных ошибок :(
                      0
                      А, ну там все прекрасно, запрос возвращает корректные данные.
                  0
                  Может поможет:

                  SET TEXTSIZE { number }: resets the @@TEXTSIZE function return value.
                  The maximum setting for SET TEXTSIZE is 2 gigabytes (GB), specified in
                  bytes.
                    0
                    Не помогает, уже пробовал. :(
                      0
                      это читали? не про вашу проблему?
                      www.west-wind.com/weblog/posts/207.aspx
                        0
                        Почитал, не про мою. Моя проблема в том, что данные теряются (скорее всего) где-то на обратном пути от сервера баз данных.
                    0
                    >>Сервер отдает данные полностью
                    то есть запрос в том же квери аналайзире все нормально отдает?
                    Хм, давно работал с ms sql 2000 через iis 6.0 — не было подобных проблем (правда через браузер, но думаю что проблема не в этом)
                      0
                      К аналайзеру у меня доступа нет, потому как к нему только члены роли sysadmin доступ имеют.
                      А так, в окне результатов все правильно.
                        0
                        iis какой кстати?
                          0
                          Сейчас не могу сказать, завтра узнаю.
                      0
                      +SELECT CONVERT(nvarchar(8000), mes_text) FROM news_text (nolock) WHERE mes_id = '%mes_id%' and source_code = 'Source1'
                        0
                        «The size (8000) given to the convert specification 'nvarchar' exceeds the maximum allowed (4000).»
                        Если исправить на varchar(8000), то содержимое просто обрезается.
                        0
                        А почему бы не циклом отдавать по кусочку?
                          0
                          Как в sql-запросе сделать цикл?
                            +1
                            DECLARE @len int, @pos int, @sort int, @buffsize int
                            SELECT @len=DATALENGTH(mes_text) FROM news_text (nolock) WHERE mes_id = '%mes_id%' AND source_code = Source1'
                            select @sort = 1, @pos = 0

                            declare @result (ne_text varchar(8000), sort int primary key clustered)
                            declare @buff varchar (8000)

                            while @pos < @len
                            begin
                            set @buffsize = 8000
                            if (@len — @pos < @buffsize)
                            @buffsize = @len — @pos
                            insert into @result (ne_text, sort)
                            SELECT SUBSTRING(mes_text, @pos, @buffsize) ne_text, 1 sort FROM news_text (nolock) WHERE mes_id = '%mes_id%' AND source_code = 'Source1'

                            set @pos = @pos + @buffsize

                            end

                            select * from @result

                            ну или что-то вроде этого
                              0
                              Вот это я понимаю, мощный изврат. :))
                              Спасибо, запишу в блокнотик, полезная информация. А проблему уже решил, щас напишу в посте каким образом.
                                0
                                Насчет апдейта: мда, сейчас как-то дико выглядят подобные ограничения…
                          0
                          У меня была похожая проблема, только MS SQL не отдавал более 4кб, помогло вот что www.barsmedia.net/2008/03/19/mssql-odbc-php/
                            0
                            У меня не апач, а IIS. :)

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                          Самое читаемое