2015-03-13 2 views
1

Я выполняю следующий запрос, чтобы «изменить порядок» обновленной таблицы в алфавитном порядке. Существует столбец с именем nOrder, который должен находиться в последовательном порядке. Я обновляю эту колонку:Почему этот запрос SQL неверно?

(отредактировано: забыл включить AND @zone = zone в моем вопросе, но та же проблема, что происходит)

UPDATE Zones 
SET nOrder = 0 WHERE stateKey = @key 

DECLARE @zone INT 
SET @zone = 1 
DECLARE @i INT 
SET @i = 1 

WHILE @zone < 4 
    BEGIN 
     WHILE EXISTS (SELECT TOP 1 cDisplay FROM Zones WHERE stateKey = @key AND zone = @zone AND nOrder = 0) 
      BEGIN 
       UPDATE Zones 
       SET nOrder = @i 
       WHERE cDisplay = (SELECT TOP 1 cDisplay FROM Zones WHERE stateKey = @key AND zone = @zone AND nOrder = 0 ORDER BY cDisplay) 
       SET @i += 1 
      END 
      SET @zone += 1 
      set @i = 1 
    END 

таблица становится:

FK zone    cDisplay    nOrder 
          . 
          . 
          . 
          . 
10 3 MD: CAROLINE, DORCHESTER, KENT   40 
10 3 MD: QUEEN ANNE'S      41 
10 3 MD: SOMERSET, TALBOT, WILCOMICO   42 
10 3 ME: PORTLAND       43 
10 3 ME: YORK        44 
          . 
          . 
          . 
          . 
10 3 TX: COUNTIES NORTH OF HOUSTON   99 
10 3 TX: DALLAS-FORT WORTH OUTER SUBURBAN 100 
10 3 TX: EL PASO       101 
10 3 TX: MATAGORDA AND VICTORIA COUNTIES 102 
10 3 TX: NORTHEAST COUNTIES     103 
10 3 TX: SAN ANTONIO OUTER SUBURBAN AREAS 104 
10 3 TX: SOUTHERN TEXAS      43 --??? 
10 3 TX: TYLER        105 
          . 
          . 
          . 
          . 

«FK» на самом деле «stateKey», но это не подходит.

Почему эта запись не работает? Для меня не имеет большого значения, что это произойдет.

У кого-нибудь есть идеи?

+0

Где инструкция 'select' с предложением' order by'? –

+0

Возможно, это только я, но единственное предложение order by, которое я вижу, - это заказать cDisplay, и если я правильно читаю, тогда «SOUTHERN TEXAS» принадлежит сразу после «SAN ANTONIO ...» – childofsoong

+0

Вывешенная таблица возвращается из 'SELECT * FROM Zones WHERE FK = 10 ORDER BY zone, cDisplay' –

ответ

6

Как насчет более простого способа сделать это? Я думаю, что вы хотите:

WITH toupdate as (
     select z.*, row_number() over (partition by zone order by cDisplay) as seqnum 
     from zones z 
     where stateKey = @key AND nOrder = 0 
    ) 
UPDATE toupdate 
    set nOrder = seqnum; 

Переменная @zone установлена, но не используется в коде (по крайней мере, это не влияет на обновление). Я не уверен, что он должен делать, но я подозреваю, что это связано с проблемой с вашим кодом. В любом случае использование CTE и функции ранжирования - лучший способ решить эту проблему.

+0

@JosephNields - Да, если вы в 2005 году, синтаксис должен быть «разделять по порядку зоны с помощью cDisplay» (без запятой). –

+0

@NoDisplayName. , , Большое спасибо. Я ценю небольшие изменения (изменение стиля отступов - другое дело;). –

-1

Вы должны использовать предложение ORDER BY всякий раз, когда используете "SELECT TOP ...", иначе вы получите неопределенный заказ, который может быть любым, что хочет оптимизатор SQL.

+5

На самом деле, «TOP 1» довольно избыточен в подзапросе 'exist'. «Порядок от» там не нужен. Итак, я думаю, «MUST» немного силен. (Примечание: я не спускал вниз, я только объясняю проблему.) –

+0

Ну, если вы выбираете TOP все, вам нужен ORDER BY или TOP не гарантированно даст вам то, что вы ожидаете. Это может СЕЙЧАС, но не гарантируется в будущем. Но вы правы, что, если он похоронен в IF EXISTS, то для этого он является излишним. Но это не меняет того факта, что использование SELECT TOP без ORDER BY - это плохая практика, период. Я только добавил в качестве ответа, потому что меня попросил оригинальный плакат. Сначала я поставил его в комментарии. – pmbAustin

+0

реалистично я мог просто удалить инструкцию 'TOP' в существующей. Но это только запускается один раз и действует примерно на 25 000 записей, поэтому эффективность не вызывает большого беспокойства. –

Смежные вопросы