在我的查询中,我必须连接不受我控制的db表。这让我很生气,因为有时这个数据库无法访问(请不要问我为什么)这会打破我的疑问。我加入的字段不是我操作的基础,我希望我的应用程序正常工作,即使这些字段一次无法访问。
这是我不拥有的数据结构:
[DBOutOfControl].[dbo].[Table1]:
[Field1]
[Field2]
[DBOutOfControl].[dbo].[Table2]:
[Field1]
[Field2]
[Field3]
这是我的表:
[DBInMyControl].[dbo].[Table3]:
[Field1]
我的原始查询看起来像这样:
SELECT [Table3].[MyID],
[ForeignDataQry].[A],
[ForeignDataQry].[B]
FROM [DBInMyControl].[dbo].[Table3]
LEFT JOIN
(SELECT [Table1].[Field1] AS [MyID],
[Table1].[Field2] AS [A],
[SubQry].[Field2] AS [B]
FROM [DBOutOfControl].[dbo].[Table1]
LEFT JOIN
(SELECT [Table2].[Field1],
[Table2].[Field2]
FROM [DBOutOfControl].[dbo].[Table2]
WHERE [Table2].[Field3] = 'Where') AS [SubQry] ON [Table1].[Field1] = [SubQry].[Field1]) AS [ForeignDataQry] ON [Table3].[MyID]=[ForeignDataQry].[MyID]
如何防止此查询,以便在[ForeignDataQry]生成错误时结果如下:
[MyID] [A] [B]
1 NULL NULL
否则
[MyID] [A] [B]
1 Va1 Val2
服务器方面有什么可以做的吗?
答案 0 :(得分:0)
只需指定COUNT
的预期结果,即三个名称,您可以事先检查表格。轻微的重写可以允许它检查除表之外的对象,如果需要,可以使用EXISTS
,跳过或添加更多检查等等:
IF 0 = ( -- Specify how many records you expect to come.
SELECT COUNT(C.[name]) AS [COUNT]
FROM sys.objects AS O
LEFT JOIN sys.schemas AS S ON S.schema_id = O.schema_id
LEFT JOIN sys.columns AS C ON C.object_id = O.object_id
WHERE O.[name] = 'tablename'
AND S.[name] = 'schemaname'
AND C.[name] = 'columnname'
)
SELECT 1 AS A -- Do some code.
ELSE
SELECT 2 AS B -- Do some other code.
答案 1 :(得分:0)
我将有问题的查询包装在动态代码中,以便能够捕获编译错误(我们无法在同一范围内捕获),如下所示:
begin try
declare @sql varchar(4000) =
'SELECT [Table3].[MyID],
[ForeignDataQry].[A],
[ForeignDataQry].[B]
FROM [DBInMyControl].[dbo].[Table3]
LEFT JOIN
(SELECT [Table1].[Field1] AS [MyID],
[Table1].[Field2] AS [A],
[SubQry].[Field2] AS [B]
FROM [DBOutOfControl].[dbo].[Table1]
LEFT JOIN
(SELECT [Table2].[Field1],
[Table2].[Field2]
FROM [DBOutOfControl].[dbo].[Table2]
WHERE [Table2].[Field3] = ''Where'') AS [SubQry] ON [Table1].[Field1] = [SubQry].[Field1]) AS [ForeignDataQry] ON [Table3].[MyID]=[ForeignDataQry].[MyID]'
exec(@sql)
end try
begin catch
SELECT [Table3].[MyID],
cast(null as ... )as [A],
cast(null as ...) as [B]
FROM [DBInMyControl].[dbo].[Table3]
end catch
在这里,我使用cast(null as ... )as [A]
获取与[ForeignDataQry].[A]
相同的类型,例如,如果[ForeignDataQry].[A]
为int,则应该为int:cast(null as int )as [A]
答案 2 :(得分:0)
我以不同的方式解决了这个问题,但最后还是:
我创建了一个[Table4]来保存外来表中记录的副本 - 字段匹配[ForeignDataQry] + timestamp。我创建了程序:
CREATE PROCEDURE [dbo].[CopyForeignData]
AS
DECLARE @Timestamp datetime
SET @Timestamp = getdate()
BEGIN
INSERT INTO [DBInMyControl].[dbo].[Table4] ([MyID], [A], [B], [Timestamp])
SELECT [Table1].[Field1] AS [MyID],
[Table1].[Field2] AS [A],
[SubQry].[Field2] AS [B],
@Timestamp
FROM [DBOutOfControl].[dbo].[Table1]
LEFT JOIN
(SELECT [Table2].[Field1],
[Table2].[Field2]
FROM [DBOutOfControl].[dbo].[Table2]
WHERE [Table2].[Field3] = 'Where') AS [SubQry] ON [Table1].[Field1] = [SubQry].[Field1]
DELETE FROM [DBInMyControl].[dbo].[Table4] WHERE [Timestamp] <> @Timestamp
END
每当我启动应用程序并在那里处理错误并修改我的主LEFT JOIN以参考[表4]
时,我会调用它