tsklab
@tsklab
Здесь отвечаю на вопросы.

Как добавить список в список без повторений?

В музыкальном альбоме для исполнителей есть список инструментов (ролей), например:
Paul McCartney: lead vocals, guitar, bass, piano, hammond organ, drums, timpani, percussion, recorder, flugelhorn
Mal Evans: backing vocals (2, 6), saxophone (23)
Как добавить список в список без повторений? Например:
Mal Evans: backing vocals (2), handclaps (2, 18), trumpet (23)
  • Вопрос задан
  • 101 просмотр
Решения вопроса 1
tsklab
@tsklab Автор вопроса, куратор тега SQL Server
Здесь отвечаю на вопросы.
CREATE TRIGGER AlbumRoleInsert ON AlbumRole INSTEAD OF INSERT AS 
BEGIN
  SET NOCOUNT ON
  DECLARE @ALB INT, @PRF INT, @ROL VARCHAR(500), @mas INT, @pla BIT, @mem BIT, @gue BIT
  DECLARE @ID INT, @RLR VARCHAR(500)
  DECLARE @Role TABLE ( [Role] VARCHAR(100) )
  
  DECLARE LISTROLE CURSOR LOCAL FAST_FORWARD FOR
    SELECT Album, [Master], Performer, Play, Member, dbo.RoleHideTrack( [Role] ), SpecialGuest
      FROM Inserted
  OPEN LISTROLE
  FETCH LISTROLE INTO @ALB, @mas, @PRF, @pla, @mem, @ROL, @gue
  WHILE @@FETCH_STATUS = 0 BEGIN
    -- Есть запись?
    IF EXISTS( SELECT * FROM AlbumRole WHERE (Album = @ALB) AND (Performer = @PRF)) BEGIN
      SELECT @ID = ID, @RLR = dbo.RoleHideTrack( [Role] ) 
        FROM AlbumRole WHERE (Album = @ALB) AND (Performer = @PRF)
      -- Есть роль?
      INSERT INTO @Role SELECT DISTINCT TRIM( value ) FROM STRING_SPLIT( @RLR, ',' )
      INSERT INTO @Role SELECT TRIM( value ) FROM STRING_SPLIT( @ROL, ',' ) 
                                               WHERE TRIM( value ) NOT IN ( SELECT [Role] FROM @Role )
      UPDATE @Role SET [Role] = TRIM( [Role] )
      DELETE @Role WHERE ([Role] = '')
      SELECT @RLR = dbo.RoleRestTrack( STRING_AGG( [Role], ', ' )) FROM @Role
      -- Обновление списка.
      UPDATE AlbumRole SET [Role] = @RLR WHERE ID = @ID
    END ELSE BEGIN
      -- Добавление: 
      SET @ROL = dbo.RoleRestTrack( @ROL )
      INSERT INTO AlbumRole ( Album, [Master], Performer, Play, Member, [Role], SpecialGuest ) 
             VALUES( @ALB, @mas, @PRF, @pla, @mem, @ROL, @gue )
    END
    -- Следующее поле
    FETCH LISTROLE INTO @ALB, @mas, @PRF, @pla, @mem, @ROL, @gue
  END
  CLOSE LISTROLE
  DEALLOCATE LISTROLE
END

Поскольку в списках есть примечания и они могут быть разделены , заменяем их перед обработкой и восстанавливаем в конце:
CREATE FUNCTION dbo.RoleHideTrack ( @RL VARCHAR(500) ) RETURNS VARCHAR(500)
WITH EXECUTE AS CALLER
AS
BEGIN
  DECLARE @TR VARCHAR(100), @HR VARCHAR(100)
  WHILE (CHARINDEX( '(', @RL) > 0 ) BEGIN
    SET @TR = SUBSTRING( @RL, CHARINDEX( '(', @RL), CHARINDEX( ')', @RL) - CHARINDEX( '(', @RL) + 1)
    SET @HR = REPLACE( REPLACE( REPLACE( @TR, ')', '}' ), '(', '{' ), ',', ';')
    SET @RL = REPLACE( @RL, @TR, @HR )
  END
  RETURN @RL
END

CREATE FUNCTION dbo.RoleRestTrack ( @RL VARCHAR(500) ) RETURNS VARCHAR(500)
WITH EXECUTE AS CALLER
AS
BEGIN
  RETURN REPLACE( REPLACE( REPLACE( @RL, '}', ')' ), '{', '(' ), ';', ',')
END
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы