以下是我的SQL查询。我想从作为变量给出的列名中选择值。除了使用动态查询之外,有没有合适的方法呢?
SELECT EPV.EmployeeCode, @RateOfEmployee, @RateOfEmployer
FROM [HR_EmployeeProvisions] EPV
答案 0 :(得分:5)
在不使用动态sql的情况下执行此操作的一种方法是使用CASE语句
但这很丑陋
SELECT EPV.EmployeeCode, case @RateOfEmployee when 'RateOfEmployee' then RateOfEmployee
when 'X' then X
..
end , case @RateOfEmployer when 'RateOfEmployer' then RateOfEmployer
when 'Y' then Y
..
end
FROM [HR_EmployeeProvisions] EPV
您必须检查CASE
声明中的所有列。
答案 1 :(得分:5)
您无法在Sql server中参数化identifiers,我怀疑它是否可以在任何其他关系数据库中使用。
您最好的选择是使用动态Sql。
请注意,动态sql通常存在安全隐患,您必须为sql injection攻击保护您的代码。
我可能会这样做:
Declare @Sql nvarchar(500)
Declare numberOfColumns int;
select @numberOfColumns = count(1)
from information_schema.columns
where table_name = 'HR_EmployeeProvisions'
and column_name IN(@RateOfEmployee, @RateOfEmployer)
if @numberOfColumns = 2 begin
Select @Sql = 'SELECT EmployeeCode, '+ QUOTENAME(@RateOfEmployee) +' ,'+ QUOTENAME(@RateOfEmployer) +
'FROM HR_EmployeeProvisions'
exec(@Sql)
end
通过这种方式,您可以确保列名实际存在于表中,并使用QUOTENAME
作为另一层安全。
注意:在您的表示层中,您应该处理由于列名无效而无法执行选择的选项。
答案 2 :(得分:3)
查看UNPIVOT子句 - 我不确定它是否适用于您的情况,但在某些情况下,它可用于通过列名查询值而无需动态SQL:
create table t1 (
a int,
b int,
c int
);
insert into t1 values
(1, 11, 111),
(2, 22, 222),
(3, 33, 333);
select a, col_name, col_value from t1
unpivot (col_value for col_name in (b, c)) as dt;
结果:
| a | col_name | col_value |
|---|----------|-----------|
| 1 | b | 11 |
| 1 | c | 111 |
| 2 | b | 22 |
| 2 | c | 222 |
| 3 | b | 33 |
| 3 | c | 333 |
如果您只需a
中的值,具体取决于(动态)b
或c
上的某些条件,您就可以构建该条件。如果您需要列b
或c
中的值,则可以添加... WHERE col_name = ?
。如果您需要更多列,则可能需要过滤未旋转表上的列值,而不是再次旋转它以将值返回到列中。