SQL处理Where子句中的Nullable外键

时间:2011-02-14 22:30:41

标签: sql sql-server sql-server-2008-r2

假设我有一个名为my_table的表,其中包含primary_key table_pk和三个分别名为X_fk,Y_fk和Z_fk的无效字段(外键),以及另一个名为data的字段。表X,Y和Z都有主键字段和名称字段(例如{X_pk,X_name},{Y_pk,Y_name},{Z_pk,Z_name})。

我想要一个查询,根据表X,Y和Z中的名称唯一返回my_table中的一行。

SELECT table_pk 
FROM my_table 
WHERE 
    X_fk = (SELECT X_pk FROM X WHERE X_name = ?) 
  AND 
    Y_fk = (SELECT Y_pk FROM Y WHERE Y_name = ?) 
  AND 
    Z_fk = (SELECT Z_pk FROM Z WHERE Z_name = ?)

当我想找到行(X_Name,Y_Name,Z_Name)=('XXX','YYY',NULL)时,这不起作用,因为Z_fk = NULL永远不会导致TRUE。如何修改上面的查询以从表中提取一个唯一条目来计算某些外键为NULL的唯一条目?

2 个答案:

答案 0 :(得分:3)

试试这个:

SELECT min(table_pk)
FROM my_table 
WHERE 
    ((X_fk = (SELECT X_pk FROM X WHERE X_name = ?)) OR (? IS NULL AND X_fk IS NULL))
AND 
    ((Y_fk = (SELECT Y_pk FROM Y WHERE Y_name = ?)) OR (? IS NULL AND Y_fk IS NULL)) 
AND 
    ((Z_fk = (SELECT Z_pk FROM Z WHERE Z_name = ?)) OR (? IS NULL AND Z_fk IS NULL))

答案 1 :(得分:2)

与LukLed相同,但输入只能从前端绑定一次

SELECT table_pk 
FROM my_table
cross join (select ? iX, ? iY, ? iZ) i
WHERE 
    ((i.iX is null and X_fk is null) OR X_fk = (SELECT X_pk FROM X WHERE X_name = i.iX))
  AND 
    ((i.iY is null and Y_fk is null) or Y_fk = (SELECT Y_pk FROM Y WHERE Y_name = i.iY))
  AND 
    ((i.iZ is null and Z_fk is null) or Z_fk = (SELECT Z_pk FROM Z WHERE Z_name = i.iZ))

这看起来更短但不做任何好的索引(假设-1不是有效值)。

SELECT table_pk 
FROM my_table
WHERE 
    Isnull(X_fk,-1) = isnull((SELECT X_pk FROM X WHERE X_name = ?),-1)
  AND 
    Isnull(Y_fk,-1) = Isnull((SELECT Y_pk FROM Y WHERE Y_name = ?),-1)
  AND 
    Isnull(Z_fk,-1) = Isnull((SELECT Z_pk FROM Z WHERE Z_name = ?),-1)