在我的动态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
;';