我在sql编写程序方面有点新意。所以请帮我解决这个问题。
我有一个包含列名的表,我想动态选择列名以从其他列中检索数据。
例如
Id colname Name Age Salary
1 Name, Age Raghu 23 20000
2 Salary Raghav 45 30000
3 Age Fizal 33 20000
NewId colName Values
1 Name,Age Raghu, 23
2 Salary 20000
3 Age 33
在#table1中,使用colname我想从其他列(Name,Age,Salary)中提取数据并创建#table2,如上例所示。我想知道实现相同的最佳方法。
答案 0 :(得分:0)
能做到吗?是。但既然你问最好的方法,我会说这样做一般的事情,并不是一个好的做法。在SQL中重载列很少是个好主意。在这种情况下重载意味着在单个字段中存储多个值,例如[values]
包含Raghu, 23
。通过将它们作为单独的列留在一起,将它们连接在一起可以获得什么好处?
我的建议是返回所有列,无论Id
如何,都取消colname
字段。然后你的查询就像这样简单:
select
Id,
Name,
Age,
Salary
from #Data
/* Returns
Id Name Age Salary
---- -------- ----- -----------
1 Raghu 23 20000
2 Raghav 45 30000
3 Fizal 33 20000
*/
是的,您将获得这些行不一定需要的列,例如Salary
Id = 1
或Name
和Age
id = 2
,但那是什么?
假设它是一个权利事物,并且您不能只显示所有人的所有列,您可以维护一个授权映射列表(在SQL或您的应用程序中),并只渲染他们有权使用的那些。 / p>
或者如果绝对无法让潜在用户无权通过网络传输数据,您仍然可以在SQL中执行此操作,但只需将其清空您不想返回的列,而不是尝试将所有授权值序列化为单个字段。最终结果是相同的,但这比动态序列化所有数据要容易得多。
执行此操作的过程可能看起来像这样。它仅适用于您提到的三个列,但您可以添加更多参数,或者让它接受字段列表,字段的XML文档或字段的表值参数。我没有采用这些方法,因为他们需要更多的参与实现,但这应该得到了想法
create table #Data
(
Id int primary key,
Name nvarchar(50),
Age int,
Salary int
)
insert into #Data (Id, Name, Age, Salary)
values
(1, 'Raghu', 23, 20000),
(2, 'Raghav', 45, 30000),
(3, 'Fizal', 33, 20000)
go
create proc #GetData
@Id int,
@ShowName bit,
@ShowAge bit,
@ShowSalary bit
as
select
ID,
Name = iif(@ShowName = 1, Name, null),
Age = iif(@ShowAge = 1, Age, null),
Salary = iif(@ShowSalary = 1, Salary, null)
from #Data
where Id = @Id
然后您将调用此过程:
-- ID: 1
exec #GetData @Id = 1, @ShowName = 1, @ShowAge = 1, @ShowSalary = 0
/*
ID Name Age Salary
----- ------- ----------- -----------
1 Raghu 23 NULL
*/
-- ID: 2
exec #GetData @Id = 2, @ShowName = 0, @ShowAge = 0, @ShowSalary = 1
/*
ID Name Age Salary
----- ------- ----------- -----------
2 NULL NULL 30000
*/
-- ID: 3
exec #GetData @Id = 3, @ShowName = 0, @ShowAge = 1, @ShowSalary = 0
/*
ID Name Age Salary
----- ------- ----------- -----------
3 NULL 33 NULL
*/