使用动态SQL循环遍历列名

时间:2013-12-09 04:48:42

标签: sql loops dynamic

我想出了一段代码,以显示每列的所有不同值,并计算每列的记录数。我希望代码循环遍历所有列。

这就是我到目前为止所拥有的......我是SQL的新手,所以请注意这一点:)

硬编码:

  select [Sales Manager], count(*)
  from  [BT].[dbo].[test]
  group by [Sales Manager]
  order by 2 desc

尝试动态SQL:

Declare @sql varchar(max),
@column as varchar(255)

    set @column = '[Sales Manager]'
    set @sql = 'select ' + @column + ',count(*) from [BT].[dbo].[test] group by ' + @column + 'order by 2 desc'

    exec (@sql)

这两项工作都很好。如何让它循环遍历所有列?我不介意我是否必须对列名进行硬编码,并且通过在每个列中为@column进行子搜索来实现。

这有意义吗?

全部谢谢!

3 个答案:

答案 0 :(得分:8)

这是一个XY答案,但是如果你不介意对列名进行硬编码,我建议你这样做,并完全避免使用动态SQL和循环。动态SQL通常被认为是最后的手段,如果不小心,会打开安全问题(SQL注入攻击),如果无法缓存查询和执行计划,通常会更慢。

如果你有大量的列名,你可以在Word中编写一段快速代码或邮件合并来代替你。


但是,就如何获取列名而言,假设这是SQL Server,您可以使用以下查询:

SELECT c.name
FROM sys.columns c
WHERE c.object_id = OBJECT_ID('dbo.test')

因此,您可以从此查询构建动态SQL:

SELECT 'select ' 
    + QUOTENAME(c.name) 
    + ',count(*) from [BT].[dbo].[test] group by ' 
    + QUOTENAME(c.name)  
    + 'order by 2 desc'
FROM sys.columns c
WHERE c.object_id = OBJECT_ID('dbo.test')

并使用游标循环。

或者将整个事物编译成一个批处理并执行。这里我们使用FOR XML PATH('')技巧:

DECLARE @sql VARCHAR(MAX) = (
    SELECT ' select ' --note the extra space at the beginning
        + QUOTENAME(c.name) 
        + ',count(*) from [BT].[dbo].[test] group by ' 
        + QUOTENAME(c.name)  
        + 'order by 2 desc'
    FROM sys.columns c
    WHERE c.object_id = OBJECT_ID('dbo.test')
    FOR XML PATH('')
)

EXEC(@sql)

注意我正在使用the built-in QUOTENAME function来转义需要转义的列名。

答案 1 :(得分:7)

您可以使用动态SQL并获取表的所有列名。然后构建脚本:

Declare @sql varchar(max) = ''
declare @tablename as varchar(255) = 'test'

select @sql = @sql + 'select [' + c.name + '],count(*) as ''' + c.name +  ''' from [' + t.name + '] group by [' + c.name + '] order by 2 desc; ' 
from sys.columns c
inner join sys.tables t on c.object_id = t.object_id
where t.name = @tablename

EXEC (@sql)

@tablename更改为您的表名称(不包含数据库或模式名称)。

答案 2 :(得分:0)

您想知道表中所有列中不同的库伦值吗?只需在以下代码中将表名Employee替换为您的表名:

private void dgvCashbook_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
{  
   DialogResult delete = MessageBox.Show("Are You Sure To Delete", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
   if (delete == DialogResult.Yes)
   {
     if (dgvCashbook.CurrentRow.Cells["ID"].Value != DBNull.Value)                                      
     {
       SqlConnection myConnection = new SqlConnection(Form1.constring);
       DataGridViewRow dgvRow = dgvCashbook.CurrentRow;
       SqlCommand cmdDataBase = new SqlCommand("simpcaDeleteRecord", myConnection);
       cmdDataBase.CommandType = CommandType.StoredProcedure;
       cmdDataBase.Parameters.AddWithValue("@ID", Convert.ToInt32(dgvCashbook.CurrentRow.Cells["ID"].Value));
       myConnection.Open();
       cmdDataBase.ExecuteNonQuery();                  
      }
    }           
 }