SQL - Looping - копировать категорию - PullRequest
2 голосов
/ 13 ноября 2009

Предположим, что таблица категорий содержит столбцы categoryId, name и parentCategoryId, где categoryId - это поле идентификатора.

Теперь, что если мне нужно будет скопировать категорию и назначить ее новому родителю? Потому что это не просто оператор вставки. Я должен вставить все подкатегории и их подкатегории и так далее. Как я буду отслеживать их поля идентичности? Мне нужно было бы назначить parentCategoryId их подкатегориям при вставке.

Этот вопрос понятен?

Ответы [ 3 ]

1 голос
/ 13 ноября 2009

Не уверен, если вы задаете 2 вопроса или только 1, то есть репликацию всей категории как новой категории (т.е. копирование категории) или повторное присвоение существующей категории новому родителю - у каждого будут разные проблемы / решения, но давайте начнем с копирования всей категории.

Во-первых, если вы используете столбец на основе идентификаторов, способ ONLY , который вы можете сделать без использования опции «set identity_insert on», будет заключаться в перемещении по всему дереву, начиная с корневые узлы и работа вниз (т.е. вставьте категорию (ии) верхнего уровня, получите вновь созданные значения идентичности, вставьте категории второго уровня и т. д.). Если вы находитесь в сценарии, в котором вы можете использовать «set identity_insert on», или если вы можете заменить использование тождеств с явными числами, то вы можете использовать приведенный ниже код.

В этом коде вы заметите использование *1008*, рекурсивных CTE и функций ранжирования , поэтому это предполагает Sql 2005 или выше. Кроме того, столбцы lvl, path и cnt просто включены для демонстрационных целей, которые вы можете использовать для просмотра, если хотите, не требуется ни в одном окончательном решении:

declare @root_category_id bigint,
        @start_new_id_value bigint;

-- What category id do we want to move?
select  @root_category_id = 3;
-- Get the current max id and pad a bit...
select  @start_new_id_value = max(categoryId)
from    Category;
select  @start_new_id_value = coalesce(@start_new_id_value,0) + 100;

-- Show our values
select  @root_category_id, @start_new_id_value;

begin tran;
set identity_insert Category on;

-- This query will give you the entire category tree
with subs (catId, parentCatId, catName, lvl, path, new_id, new_parent_id, cnt) as (
    -- Anchor member returns a row for the input manager
    select  catId, parentCatId, catName, 0 as lvl,
            cast(cast(catId as varchar(10)) as varchar(max)) as path,
            @start_new_id_value + row_number() over(order by catId) - 1 as new_id, 
            cast(parentCatId as bigint) as new_parent_id, 
            count(*) over(partition by 0) as cnt
    from    Category
    where   catId = @root_category_id

    union all

    -- recursive member returns next level of children
    select  c.catId, c.parentCatId, c.catName, p.lvl + 1,
            cast(p.path + '.' + cast(catId as varchar(10)) as varchar(max)),
            p.cnt + row_number() over(order by c.catId) + p.new_id - 1 as new_id,
            p.new_id as new_parent_id,
            count(*) over(partition by p.lvl) as cnt
    from    subs as p -- Parent
    join    Category as c -- Child
    on      c.parentCatId = p.catId
)
-- Perform the insert
insert  Category 
        (categoryId, Name, parentCategoryId)
select  s.catId, s.catName, s.parentCatId
from    subs s
--order by path;

set identity_insert Category off;
commit tran;
0 голосов
/ 13 ноября 2009

Вам известны вложенные множества? Это альтернативный способ представления данных в подобных задачах. Я не знаю, поможет ли это здесь, но если вы не знаете об этом, вы можете рассмотреть это. http://intelligent -enterprise.informationweek.com / 001020 / celko.jhtml

0 голосов
/ 13 ноября 2009

Интересный вопрос.

Если вы работаете в SQL 2005+, я полагаю, вы могли бы создать CTE с полным деревом категории для репликации, что поместит его во временную папку для работы, вне основной таблицы.

Затем вы можете использовать курсор, чтобы пройти вниз по дереву и обновить идентификационный номер родителя ...

Теперь, когда я его набираю, это не кажется самым эффективным решением. Возможно, вы могли бы вместо этого сделать причудливый оператор SELECT, который обновляет идентификатор родительского идентификатора, так как он SELECT ing?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...