109: (Default)
109 ([personal profile] 109) wrote2003-06-12 11:32 am

update column by it's index

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

итак, есть некая таблица MyTable на ms sql server. в таблице есть непрерывный ряд полей типа int, например, с 10-го по 20-е поле. и есть ещё одно поле, содержащее индекс поля, которое нужно проапдейтить, причём новое значение поля зависит от старого значения отдельно вычисляемым образом.

единственное решение, которое я нашёл, заключается в написании Get и Set stored procedures, в каждой из которых будет уродливый case. решение, очевидно, плохое, поскольку при изменении имён полей или их порядка всё будет ломаться. есть ли лучшее решение?

[identity profile] piggymouse.livejournal.com 2003-06-12 09:12 am (UTC)(link)

Ключевое слово: EXECUTE.

declare @cmd varchar(255)
set @cmd = /* трам-пам-пам */
execute(@cmd)

[identity profile] piggymouse.livejournal.com 2003-06-12 09:12 am (UTC)(link)
Это, разумеется, было не решение, а намёк на таковое.

[identity profile] 109.livejournal.com 2003-06-12 09:48 am (UTC)(link)
да, это моя ошибка, что я не упомянул, что execute (и иже с ним, типа sp_executesql) я, разумеется, рассматривал, но так и не понял, как мне извлечь с помощью них значение поля. напиши чуть более детально, если не трудно. можешь предполагать, что имя поля уже известно (вытащено с помощью COL_NAME()).

[identity profile] piggymouse.livejournal.com 2003-06-16 01:16 am (UTC)(link)

в таблице есть непрерывный ряд полей типа int… и есть ещё одно поле, содержащее индекс поля — предполагаем mytable.col_N и mytable.col_index

имя поля уже известно (вытащено с помощью COL_NAME() — предполагаем function col_name(@col_index integer) returns varchar(255)

новое значение поля зависит от старого значения отдельно вычисляемым образом — предполагаем function updated_col_value_N(@old_col_value_N integer) returns integer

Предлагаемый код для обновления одной строки таблицы mytable (в примере она задаётся неприписанным условием where). Если нужно обновить более одной строки, предлагается обновлять их по одной.

declare @sColName varchar(255)
declare @nColIndex integer
select @nColIndex = col_index from mytable where ...
declare @sCmd varchar(255)
set @cmd = 'update mytable set ' + col_name(@nColIndex) +
        '=updated_col_value_' + cast(@nColIndex as varchar(32)) +
        '('  + col_name(@nColIndex) + ') where ...'
execute(@cmd)

Re:

[identity profile] 109.livejournal.com 2003-06-16 05:32 am (UTC)(link)
о, спасибо. а просто извлечь значение поля с помощью dynamic sql - никак, я правильно понимаю? то есть sp_executesql может быть с параметром, но он, как я понял, не может быть output.

[identity profile] piggymouse.livejournal.com 2003-06-16 06:13 am (UTC)(link)
Есть ощущение, что ты прав и извлекать информацию изнутри exec/sp_executesql, скажем так, затруднительно. Приходят в голову идеи о временной таблице, видимой из обоих batch'ей (вызывающего и вызываемого). В твоём случае, кажется, без этого можно обойтись. Параметров у sp_executesql, кстати, может быть много.

[identity profile] 109.livejournal.com 2003-06-12 08:37 pm (UTC)(link)
нет, правда. я сейчас ещё час парил себе голову, но так и не придумал. как?

Я, конечно, не доктор..

[identity profile] caseq.livejournal.com 2003-06-13 03:45 am (UTC)(link)
.. но просто любопытно -- а дизайн базы уже обсуждению не подлежит? Просто мне кажется логичным утащить этот десяток полей в отедлную табличку, и сделать view'шку где они join'ятся по ключу записи в начальной таблички + номеру поля. Отдельная польза такого решения -- если со временем их может становиться больше.

Re: Я, конечно, не доктор..

[identity profile] 109.livejournal.com 2003-06-13 06:01 am (UTC)(link)