SQL Server 2000 выдает ошибку при запросах, которые содержат более 12500 условий - PullRequest
1 голос
/ 27 августа 2009

У меня проблема с SQL Server 2000 и запросами, которые содержат большое количество условий. Когда эти запросы отправляются на SQL Server, я получаю одно из следующих сообщений об ошибках в зависимости от запроса (сообщения об ошибках, отредактированные для удобства чтения):

[Microsoft][ODBC SQL Server Driver][SQL Server]
SqlDumpExceptionHandler: 
Process 61 generated fatal exception c0000005 EXCEPTION_ACCESS_VIOLATION. 
SQL Server is terminating this process. (SQL-HY000)

или

[Microsoft][ODBC SQL Server Driver][SQL Server]
The server encountered a stack overflow during compile time. (SQL-42000)

Предел составляет около 12500 условий.

  1. Кто-нибудь еще сталкивался с такими же проблемами?
  2. Есть ли в SQL Server 2000 какие-либо параметры, которые можно настроить, чтобы в запросе было больше условий?
  3. Обрабатывает ли SQL Server 2005 больше условий в запросе, чем SQL Server 2000?

--- Редактировать

Запросы, о которых идет речь, обычно имеют следующую форму

SELECT
...
FROM 
    TABLE
WHERE
    -- the rows I want
    ( ( COLUMN2 = a AND COLUMN3 = b ) OR ( ( COLUMN2 = c AND COLUMN3 = d ) ) 
    AND
    COLUMN1 NOT IN ( ... ) -- The rows that I don't want

Комбинации для COLUMN2 и COLUMN3 могут быть где-то между 20000 и 60000, я думаю, хотя точное число в настоящее время неизвестно.

Значения для COLUMN2 и COLUMN3 не соответствуют шаблону, поэтому невозможно упростить запрос настолько, чтобы вообще избежать проблемы.

Это значение в выражении IN также может достигать примерно того же числа.

--- Редактировать 2

Решение:

Это решение, которое я выбрал. Как минимум пока какие-то новые проблемы всплывают.

  1. Сначала запрос разбивается на несколько запросов. Вместе все запросы покрывают строки для выбора. Это позволяет избежать ограничения условий в SQL Server, а также, по-видимому, значительно повысить эффективность в тех случаях, когда ограничение также не было достигнуто.
  2. Затем результат каждого запроса объединяется с помощью UNION.
  3. Затем общий результат фильтруется приложением вместо SQL Server. Это кажется достаточно эффективным в этом случае. Если в дальнейшем это окажется неэффективным, это, вероятно, можно будет заменить наброском решения в ответе ниже.

Ответы [ 2 ]

0 голосов
/ 27 августа 2009

Если вам действительно нужны тысячи условий для запроса, и вы не можете упростить его с помощью диапазонов, вы можете попытаться объединить временную таблицу. Создайте временную таблицу со значениями в ней, а затем добавьте INNER к ней в своем запросе, которая отфильтрует эти значения в таблице.

из чего-то вроде (только предположение, OP не предоставил пример кода):

SELECT
    *
    FROM MyTale
    WHERE (a=5 AND b='apple' AND c=1024)
        OR (a=3 AND b='pear' AND c=2048)
        OR (a=8 AND b='apple' AND c=2048)
        ....

до:

CREATE TABLE #TempJoin
(a int
,b char(10)
,c int
)

INSERT INTO #TempJoin VALUES (5,'apple',1024)
INSERT INTO #TempJoin VALUES (3,'pear',2048)
INSERT INTO #TempJoin VALUES (8,'apple',2048)
....

SELECT
    m.*
    FROM MyTale              m 
        INNER JOIN #TempJoin t ON m.a=t.a AND m.b=t.b AND m.c=t.c

РЕДАКТИРОВАТЬ на основе редактирования ОП ...
Я все еще очень озадачен "почему" так много условий. Я просто не могу себе представить, почему, не могли бы вы немного рассказать о природе проблемы, которую вы пытаетесь решить?

Откуда все все значения, используемые в условиях? пользовательский ввод, файл, другая таблица базы данных?

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

Единственный способ решить вашу проблему (как представлено) - сохранить ваши условия в виде строк в двух таблицах: RowsToKeep и RowsToRemove. Вы можете использовать обычные таблицы, таблицы #temp или таблицы ## globalTemp. Вы не даете достаточно информации, чтобы рекомендовать, какой из них использовать (как часто выполняется этот запрос? Будет ли одновременно выполняться несколько похожих запросов и т. Д.). В моем примере кода я буду использовать обычную таблицу и предположим, что ничто не помешает обычным таблицам (никто другой не будет пытаться использовать / изменять RowsToKeep и RowsToRemove, пока этот запрос готовится или выполняется).

CREATE TABLE RowsToKeep
(a int       --you don't say the data type, but you can make these anything
,b char(10)  --you don't say the data type, but you can make these anything
)

CREATE TABLE RowsToRemove
(c int       --you don't say the data type, but you can make these anything
)

Для такого запроса, как вы описали, я бы предположил, что вы строите его динамически, используя циклы. Сначала TRUNCATE или DELETE для двух таблиц, а затем по мере зацикливания INSERT INTO этих таблиц вместо построения условий динамического запроса. После вставки всех значений вы можете использовать следующий простой запрос, который будет функционировать так же, как ваш оригинал, но не будет ограничен количеством условий:

SELECT
...
    FROM TABLE                        t
        INNER JOIN RowsToKeep         k ON t.Column2=k.a AND t.Column3=k.b
        LEFT OUTER JOIN RowsToRemove  r ON t.Column1=r.a
    WHERE r.a IS NULL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...