是否可以检索动态SQL中的值?

时间:2016-09-02 01:07:35

标签: sql-server dynamic-sql information-schema case-statement

在我的动态sql字符串中,我有两个变量:

col(列名)和val(列值)。

在我的动态sql中我需要基本检查(在case语句中)col是否为ID列,如果是,则通过查找表来检索name列。

示例:

如果col ='LocationId'且val = 7,那么我需要从t_location中选择LocationName,其中LocationId = 7

'When'语句如下:

set @sql = 
    '
when  
(
    select COUNT(*) 
    from 
        INFORMATION_SCHEMA.COLUMNS 
    where 
        TABLE_NAME like ''t_'' + REPLACE(col,''Id'','''') and
        (COLUMN_NAME = col or COLUMN_NAME = REPLACE(col,''Id'','''')+''Name'')
) > 1...

但我不确定如何实现'Then'语句

+'then 
(select '+ <name_column> + 
' from ' + <table_name> + 
' where ' + <id_column> + ' = val)';

如果col ='LocationId'那么 name_column ='LocationName',table_name ='t_location'和id_column ='LocationId'

首先检索name_column,它看起来像

Select 
    COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS
where 
    TABLE_NAME = like ''t_'' + REPLACE(col,'Id','') and
    COLUMN_NAME = REPLACE(col,'Id','')+'Name'

除了'col'在我的动态sql字符串中,并且会抛出错误,因为此语句在字符串之外。所以这不起作用:

+'then 
    (select '+ 
        (Select 
            COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS
        where 
            TABLE_NAME = like 't_' + REPLACE(col,'Id','') and
            COLUMN_NAME = REPLACE(col,'Id','')+'Name'
        ) + '
    from.....';

我别无选择,只能使用动态sql。有没有办法让这项工作?还是更好的方法?这只是怪物动态sql字符串的摘录,所以我不得不将其保存在动态sql中,以便其余的工作。

更新
这是存储过程中的完整代码:

(我想替换'当col ='..''然后......'更干的东西)

declare 
        @Sql nvarchar(max) = 'create table #table (Id int, DateChanged datetime, Change nvarchar(max), ChangedBy varchar(500), BatchName nvarchar(500), TableName nvarchar(500));
        ';
    declare
        @TableName nvarchar(255) = '';

    declare clCursor cursor for
    select Item from dbo.udf_split_max(@Tables,',')

    open clCursor
    fetch next from clCursor into @TableName
    while @@FETCH_STATUS = 0
        begin

            if exists (select * from INFORMATION_SCHEMA.columns where TABLE_NAME = 

@TableName and COLUMN_NAME = @Key)
                    begin
                        declare
                            @ArchiveTableName nvarchar(255) = dbo.ReplaceFirstInstanceInString(@TableName,'t_','archive_'),
                            @ColumnName nvarchar(255) = '',
                            @OrdinalPosition int = 0,
                            @DataType nvarchar(255) = '',
                            @CharacterMaxLength nvarchar(50) = '',
                            @PK nvarchar(255) = @Key,
                            @ArchivePK nvarchar(255) = REPLACE('Archive'+dbo.PROPERCASE(REPLACE(dbo.ReplaceFirstInstanceInString(@TableName,'t_',''),'_',' '))+'Id',' ',''),
                            @NumOfColumns int = (select count(COLUMN_NAME) from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @TableName );

                        set @Sql = @Sql +
            'with cv as (
                select
                    '+@PK+', UserId, ArchiveDateAddedUtc, Reason, [Action], col, val
                from
                    (select
                        '+@PK+', UserId, ArchiveDateAddedUtc, Reason, 
                        ';
                        set @OrdinalPosition = 1;
                        while @OrdinalPosition <= @NumOfColumns
                            begin
                                set @ColumnName = CONVERT(nvarchar(255),(select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @TableName and ORDINAL_POSITION = @OrdinalPosition));

                                if lower(@ColumnName) <> 'userid' and lower(@ColumnName) <> lower(@PK) and lower(@ColumnName) <> 'archivedateaddedutc' and lower(@ColumnName) <> 'reason' and lower(@ColumnName) <> 'action'
                                    begin
                                        set @Sql = @Sql +
                        'CAST('+@ColumnName + ' as varchar(8000)) as '+@ColumnName+',
                        ';
                                    end
                                set @OrdinalPosition = @OrdinalPosition + 1;

                            end
                        set @Sql = @Sql +
                        '[Action]
                    from
                        '+@ArchiveTableName+') t

                    unpivot (val for col in (';
                        set @OrdinalPosition = 1;
                        while @OrdinalPosition <= @NumOfColumns
                            begin
                                set @ColumnName = CONVERT(nvarchar(255),(select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @TableName and ORDINAL_POSITION = @OrdinalPosition));

                                if lower(@ColumnName) <> 'userid' and lower(@ColumnName) <> lower(@PK) 
                                    and lower(@ColumnName) <> 'archivedateaddedutc' 
                                    and lower(@ColumnName) <> 'reason' and lower(@ColumnName) <> 'action'
                                    begin
                                        set @Sql = @Sql +@ColumnName;
                                        if ((select top 1 ORDINAL_POSITION from information_schema.columns where TABLE_NAME = @TableName 
                                                and lower(COLUMN_NAME) <> 'userid' and lower(COLUMN_NAME) <> lower(@PK) 
                                                and lower(COLUMN_NAME) <> 'archivedateaddedutc' and lower(COLUMN_NAME) <> 'reason' and lower(COLUMN_NAME) <> 'action' 
                                                order by ORDINAL_POSITION desc) <> @OrdinalPosition)
                                            begin
                                                set @Sql = @Sql + ', ';
                                            end
                                        else
                                            begin
                                                set @Sql = @Sql + ')) as unpvt
                                                where '+@PK+' = '+convert(nvarchar(100),@Id);
                                            end
                                    end
                                set @OrdinalPosition = @OrdinalPosition + 1;
                            end
                        set @Sql = @Sql +
            '),
            cvr as (
                select cv.*,
                ROW_NUMBER() over (partition by '+@PK+', col order by ArchiveDateAddedUtc) as seqnum_all
                from
                    (select cv.*,
                        ROW_NUMBER() over (partition by '+@PK+', col, thegroup order by ArchiveDateAddedUtc) as seqnum_group
                    from
                        (select cv.*,
                            (ROW_NUMBER() over (partition by '+@PK+', col order by ArchiveDateAddedUtc) - 
                            ROW_NUMBER() over (partition by '+@PK+', col, val order by ArchiveDateAddedUtc)
                            ) as thegroup
                        from cv
                        ) cv
                    ) cv
                ), [raw] as (
            select cvr.*, cvrprev.val as preval, '''+@TableName+''' as [TableName]
            from cvr left outer join
                 cvr cvrprev
                 on cvr.'+@PK+' = cvrprev.'+@PK+' and
                    cvr.col = cvrprev.col and
                    cvr.seqnum_all = cvrprev.seqnum_all + 1)
            insert into #table (Id,DateChanged,Change,ChangedBy,BatchName,TableName)
            select distinct top 15
                '+convert(nvarchar(50),@Id)+' as [Id],
                ArchiveDateAddedUtc as [DateChanged],
                    case 
                        when [Action] = ''Insert'' then 
                            case 
                                when TableName = ''t_pib'' and col = ''PibsMl''
                                    then REPLACE(dbo.SpaceBeforeCap(col),''Id'','''') + '' was changed from '' + convert(nvarchar(255),ISNULL(preval,0)) + '' to '' + convert(nvarchar(255),val)
                                    else ''Record Inserted'' end
                        when [Action] = ''Update'' then 
                                case when len(col) < 4 then col
                                else REPLACE(REPLACE(REPLACE(REPLACE(dbo.SpaceBeforeCap(col),''Id'',''''),'' Utc'',''''),''Number'',''#''),''Num'',''#'') end
                            + '' was changed from '' +
                            case 
                                when Lower(col) = ''statusid'' then (select StatusName from t_status where CONVERT(nvarchar(50),StatusId) = preval) 
                                when Lower(col) = ''locationid'' then (select LocationName from t_location where CONVERT(nvarchar(50),LocationId) = preval) 
                                when Lower(col) = ''batchid'' then (select BatchName from t_batch where CONVERT(nvarchar(50),BatchId) = preval) 
                                when Lower(col) = ''vatid'' then (select VatName from t_vat where CONVERT(nvarchar(50),VatId) = preval) 
                                when Lower(col) = ''isarchived'' then case when preval = ''1'' then ''True'' else ''False'' end 
                                when Lower(col) = ''isolateid'' then (select IsolateName from t_isolate where CONVERT(nvarchar(50),IsolateId) = preval) 
                                when Lower(col) = ''batchtypeid'' then (select BatchTypeName from t_batch_type where CONVERT(nvarchar(50),BatchTypeId) = preval) 
                                --when  
                                --  (
                                --      select COUNT(*) 
                                --      from 
                                --          INFORMATION_SCHEMA.COLUMNS 
                                --      where 
                                --          TABLE_NAME like ''t_'' + REPLACE(col,''Id'','''') and
                                --          (COLUMN_NAME = col or COLUMN_NAME = REPLACE(col,''Id'','''')+''Name'')
                                --  ) > 1
                                --then
                                --  ''condition satisfied''--(select '+ '<column>' +' from '+'<table>'+' where '+'<id>'+' = preval)
                                when 
                                    Lower(col) like ''%utc'' 
                                then 
                                    REPLACE(convert(nvarchar(255),convert(date,preval),106), '' '',''-'')
                                else preval end
                            +'' to ''+
                            case 
                                when Lower(col) = ''statusid'' then (select StatusName from t_status where CONVERT(nvarchar(50),StatusId) = val) 
                                when Lower(col) = ''locationid'' then (select LocationName from t_location where CONVERT(nvarchar(50),LocationId) = val) 
                                when Lower(col) = ''batchid'' then (select BatchName from t_batch where CONVERT(nvarchar(50),BatchId) = val) 
                                when Lower(col) = ''vatid'' then (select VatName from t_vat where CONVERT(nvarchar(50),VatId) = val) 
                                when Lower(col) = ''isarchived'' then case when val = ''1'' then ''True'' else ''False'' end 
                                when Lower(col) = ''isolateid'' then (select IsolateName from t_isolate where CONVERT(nvarchar(50),IsolateId) = val) 
                                when Lower(col) = ''batchtypeid'' then (select BatchTypeName from t_batch_type where CONVERT(nvarchar(50),BatchTypeId) = val) 

                                when Lower(col) like ''%utc'' then REPLACE(convert(nvarchar(255),convert(date,val),106), '' '',''-'')
                                else val end
                        when [Action] = ''Delete'' then ''Record Deleted'' end
                as [Change],
                    ISNULL((select UserName from AspNet_Users u where u.UserId = [raw].UserId), ''User Unknown'') 
                as [ChangedBy],
                        ' 
                        +
                            -- BATCH NAME
                        case 
                            when exists (select * from information_schema.columns where COLUMN_NAME = 'BatchId' and TABLE_NAME = @TableName) 
                            then '(select top 1 b.BatchName from '+@TableName+' tbl inner join t_batch b on b.BatchId = tbl.BatchId where tbl.'+@PK+' = '+convert(nvarchar(50),@Id)+')'
                            else '''''' end 
                        +
                        '
                as [BatchName],
                TableName
            From [raw]
            where (preval <> val COLLATE Latin1_General_CS_AS 
                or (preval is null and thegroup = 0)
                or ([Action] = ''Delete'' and thegroup = 0))
                and (case when [Action] = ''Insert'' then ''Record Inserted''
                    when [Action] = ''Update'' then REPLACE(dbo.SpaceBeforeCap(col),''Number'',''#'') + '' was changed from ''+preval+'' to ''+val 
                    when [Action] = ''Delete'' then ''Record Deleted'' end) is not null
            order by ArchiveDateAddedUtc desc;
            ';                  
                    end
                    fetch next from clCursor into @TableName
            end
            close clCursor
            deallocate clCursor
        set @Sql = @Sql +
        ';
        select 
            top '+CONVERT(NVARCHAR(20),@NumRecords)+' *
        from
            #table
        where
            (Change <> ''Record Inserted'')
        order by
            DateChanged desc
        ;';

0 个答案:

没有答案