2013-06-03 51 views
3

SQL Server的问题列:SQL服务器:与外键的列表

我有一个包含外键的表列的表

| ID | PRICE | LIST_OF_FOREIGN_IDS | 
------------------------------------ 
| 3 | 89 | 67,68,69 | 
| 4 | 120 | 45,46 | 

我需要一个ID和一个视图单行FOREIGN_ID

| ID | PRICE | FOREIGN_ID | 
--------------------------- 
| 3 | 89 | 67 | 
| 3 | 89 | 68 | 
| 3 | 89 | 69 | 
| 4 | 120 | 45 | 
| 4 | 120 | 46 | 

有没有人知道从第二个表中获取数据的解决方案?

+6

这是可怕的数据库设计。返回并将'list_of_foreign_ids'分解为单个值列是否太晚了?将多个值放在这样一个列中会让你的生活变得更加痛苦。 –

+1

使用[split this function](http://stackoverflow.com/a/2507408/119477)并加入结果。 –

+2

@NikolaMitev你可以使用游标,但你不必 –

回答

5

如果可能的话,您需要修复此表上的数据库设计,以避免存储逗号分隔值列表。这将很难维持。

理想的情况下你的表结构可以改变类似以下内容:

create table item_details 
(
    id int, 
    price int 
); 

create table foreign_details 
(
    id int, 
    details varchar(50) 
); 

create table item_foreign 
(
    item_id int, 
    foreign_id int 
); 

然后你会使用查询得到的结果:

select i.id, i.price, f.id 
from item_details i 
inner join item_foreign ifd 
    on i.id = ifd.item_id 
inner join foreign_details fd 
    on ifd.foreign_id = f.id 

如果你不能修复当前的表结构,然后您可以使用拆分功能将数据分成多行。样本函数可以是:

CREATE FUNCTION [dbo].[Split](@String varchar(MAX), @Delimiter char(1))  
returns @temptable TABLE (items varchar(MAX))  
as  
begin  
    declare @idx int  
    declare @slice varchar(8000)  

    select @idx = 1  
     if len(@String)<1 or @String is null return  

    while @idx!= 0  
    begin  
     set @idx = charindex(@Delimiter,@String)  
     if @idx!=0  
      set @slice = left(@String,@idx - 1)  
     else  
      set @slice = @String  

     if(len(@slice)>0) 
      insert into @temptable(Items) values(@slice)  

     set @String = right(@String,len(@String) - @idx)  
     if len(@String) = 0 break  
    end 
return 
end; 

然后您将使用交叉适用于逗号通过分隔列表类似于此的每一行:

select t.id, t.price, 
    c.items foreign_id 
from yt t 
cross apply dbo.split(t.LIST_OF_FOREIGN_IDS, ',') c; 

SQL Fiddle with Demo

0

如果这些外国关键的ID,那么你有另一个表包含所有这些。以下不是特别有效的方法,但它避免了必须定义另一个函数。

select t.id, t.price, ft.foreign_id 
from t join 
    foreigntable ft 
    on ','+LIST_OF_FOREIGN_IDS +',' like '%,'+cast(ft.foreign_id as varchar(255))+',%' 

这是使用like方法查找字符串中的东西。它为每一端添加了分隔符。搜索“1”实际上是搜索“,1”,因此它不匹配“10”。

你可以很容易地创建视图:

create myview as 
    select t.id, t.price, ft.foreign_id 
    from t join 
     foreigntable ft 
     on ','+LIST_OF_FOREIGN_IDS +',' like '%,'+cast(ft.foreign_id as varchar(255))+',%'