关于T-SQL中的游标 - 如何将列名称作为字段名称

时间:2018-04-11 23:01:15

标签: sql-server tsql cursor

if my tables are not clear,我试图找到普通表和审计表之间的差异。

Iam_audit:

A_n   L_name       A_status   
---------------------------
1     abc          AL       
2     def          AC       

a_n   audit_field        field_after    
-------------------------------------
1     L_name             abd    
1     a_status           AL 
2     L_name             def    
2     a_status           AD 

预期:

a_n   field_after   audit_field   a_n   name
--------------------------------------------
1      abc           l_name        1    abd

a_n   field_after   audit_field   a_n   name
2      AC            a_status      2    AD

当前

a_n   field_after   audit_field   a_n   name
-----------------------------------------------
1     abc           l_name        1     l_name
2     def           l_name        1     l_name

a_n   field_after   audit_field   a_n   name
1     AL            a_status      1     a_status
2     AC            a_status      2     a_status

问题在于iam_audit它是一个列名,而在Iam中它是一个列本身。我有更多的列来比较使用光标。有解决方案吗

(查看附上的图片以获得清晰的图片)

declare @af varchar(500)
set @af = 'L_Name,A_Status'

declare @pa varchar(50)

declare audit_cur cursor for
     select ltrim(rtrim(Parameter)) 'Audit_FLD' 
     from phngeneral.dbo.fcn_TheDelimiterEliminator(@af,',')

OPEN audit_cur
FETCH NEXT FROM audit_cur into @pa

WHILE @@FETCH_STATUS = 0
BEGIN
    select *
    from
        (select  a.A_n, a.field_after, audit_field
         from Db.iam_audit a
         where a.Audit_Field = @af) i
    left join
        (select distinct a_n, @pa as name
         from Db.iam) il on i.a_n = il.a_n 
    where 
        i.audittable_field_after <> il.name
    order by 
        1 desc

    FETCH NEXT FROM audit_cur into @pa
END

CLOSE audit_cur
DEALLOCATE audit_cur

2 个答案:

答案 0 :(得分:1)

我也认为你可以像HABO所说的那样使用动态SQL。

您需要生成并执行以下查询

SELECT a.A_n,i.audit_field,a.L_name field_value,i.field_after
FROM Iam_audit a
JOIN Iam i ON i.audit_field='L_name' AND i.A_n=a.A_n AND a.L_name<>i.field_after

SELECT a.A_n,i.audit_field,a.A_status field_value,i.field_after
FROM Iam_audit a
JOIN Iam i ON i.audit_field='A_status' AND i.A_n=a.A_n AND a.A_status<>i.field_after

演示表和数据

create table Iam_audit(A_n int,L_name varchar(10),A_status varchar(10))

insert Iam_audit(A_n,L_name,A_status)values
(1,'abc','AL'),
(2,'def','AC')

create table Iam(a_n int,audit_field varchar(10),field_after varchar(10))

insert Iam(a_n,audit_field,field_after)values
(1,'L_name','abd'),
(1,'a_status','AL'),
(2,'L_name','def'),
(2,'a_status','AD')

最终解决方案

declare @af varchar(500) = 'L_Name,A_Status'

declare @pa varchar(50)

-- I think you can replace it to your cursor version with fcn_TheDelimiterEliminator
declare audit_cur cursor for
     select distinct audit_field
     from Iam
     where concat(',',@af,',') like concat('%,',audit_field,',%')

/*
declare audit_cur cursor for
     select ltrim(rtrim(Parameter)) 'Audit_FLD' 
     from phngeneral.dbo.fcn_TheDelimiterEliminator(@af,',')
*/

OPEN audit_cur
FETCH NEXT FROM audit_cur into @pa

declare @cmd varchar(1000)

WHILE @@FETCH_STATUS = 0
BEGIN

    set @cmd=concat('SELECT a.A_n,i.audit_field,a.',@pa,' field_value,i.field_after
FROM Iam_audit a
JOIN Iam i ON i.audit_field=''',@pa,''' AND i.A_n=a.A_n AND a.',@pa,'<>i.field_after')

    print @cmd -- for debug

    exec(@cmd)

    FETCH NEXT FROM audit_cur into @pa
END

CLOSE audit_cur
DEALLOCATE audit_cur

不要忘记在任何地方添加Db.前缀。

我认为您在示例中混淆了表Iam_auditIam的名称。也许你需要交换他们的名字。

答案 1 :(得分:0)

这可能听起来很傻。但是我试图再添加一个名为modifeid date的列并尝试获取最后修改日期值,但是我得到&#34;必须声明标量变量@ pa&#39;错误。

create table #Iam_audit(A_n int,L_name varchar(10),A_status varchar(10))

insert #Iam_audit(A_n,L_name,A_status)values
(1,'abc','AL'),
(2,'def','AC')

    create table #Iam(a_n int,audit_field varchar(10),field_after varchar(10),[Modified_Date] [datetime])

    insert #Iam(a_n,audit_field,field_after,[Modified_Date])values
    (1,'L_name','abd','2006-05-10 00:57:44.467'),
    (1,'a_status','AL','2005-05-10 00:57:44.467'),
    (1,'L_name','abdd','2009-05-10 00:57:44.467'),
    (1,'a_status','AL','2009-05-10 00:57:44.467'),
    (2,'L_name','def','2005-05-10 00:57:44.467'),
    (2,'a_status','AD','2007-05-10 00:57:44.467'),
    (2,'L_name','def','2006-05-10 00:57:44.467'),
    (2,'a_status','AD','2008-05-10 00:57:44.467')

declare @af varchar(500) = 'L_Name,A_Status'

declare @pa varchar(50)

declare audit_cur cursor for
     select distinct audit_field
     from #Iam
     where concat(',',@af,',') like concat('%,',audit_field,',%')

OPEN audit_cur
FETCH NEXT FROM audit_cur into @pa

declare @cmd varchar(1000)

WHILE @@FETCH_STATUS = 0
BEGIN

    set @cmd=concat('SELECT a.A_n,i.audit_field,a.',@pa,' field_value,i.field_after
FROM #Iam_audit a
JOIN (Select  a.A_n,  a.field_after,audit_field
from #iam a(nolock)
inner join (Select a_n, max(Modified_Date) as maxdate
        from #iam a2(nolock)
        where a2.Audit_field=@pa
        group by a_n
        ) as aa  on aa.a_n = a.a_n  and aa.maxdate=a.modified_Date
        where a.Audit_Field=@pa ) i 
ON i.audit_field=''',@pa,''' AND i.A_n=a.A_n AND a.',@pa,'<>i.field_after')

print @cmd -- for debug

    exec(@cmd)

    FETCH NEXT FROM audit_cur into @pa
END

CLOSE audit_cur
DEALLOCATE audit_cur