视图、存储过程或表定义函数
Posted
技术标签:
【中文标题】视图、存储过程或表定义函数【英文标题】:View, Stored Procedure, or Table Defined Function 【发布时间】:2011-01-26 20:17:44 【问题描述】:此查询按原样执行。但是,SQL Management Studio 不会将其保存为视图,因为我定义了一个变量。
声明@HighestTransaction int SET @HighestTransaction = (SELECT MAX(CardID) FROM dbo.Transactions) 选择上传。*,交易。* 从上传左外连接 dbo.Transactions ON dbo.Uploads.Code = dbo.Transactions.CardID WHERE (Uploads.Code > CASE WHEN @HighestTransaction 为 NULL THEN -1 ELSE @HighestTransaction END)我并没有真正玩过存储过程或用户定义的函数,所以我不确定最好的方法来做这件事。或者,如果有更好的写法,我也愿意接受建议。
【问题讨论】:
并在选择中指定你想要的字段。 Select * 是一种特别糟糕的编码实践,因为您有一个联接,所以您将返回一个字段两次,这是一种资源浪费。 如果其中一个表有几个列,另一个是非常具体的视图,并且所有生成的列都将被调用者使用,那么 SELECT * 是否会出现问题?无论如何,我写 SELECT * 是为了节省空间而不是分散其他东西的注意力。真正的查询确实会扩展所有列,因为当您输入 SELECT * 时,VS 和 SQL Management Studio 都会自动执行此操作。 【参考方案1】: 您可以将 MAX 隔离到 CTE 中 没有 GROUP BY 的 MAX 给出一行,所以你在那里使用 ISNULL类似...
WITh cHighestCard AS
(
SELECT ISNULL(MAX(CardID), -1) AS MaxCard FROM dbo.Transactions
)
SELECT STAUpload.*, Transactions.*
FROM dbo.STAUpload LEFT OUTER JOIN
dbo.Transactions ON dbo.STAUpload.Code = dbo.Transactions.CardID
WHERE dbo.STAUpload.Code > MaxCard --edit, error spotted by martin
编辑:不需要 CTE:它混合了集合和标量。哎呀。
SELECT STAUpload.*, Transactions.*
FROM dbo.STAUpload LEFT OUTER JOIN
dbo.Transactions ON dbo.STAUpload.Code = dbo.Transactions.CardID
WHERE dbo.STAUpload.Code >
(SELECT ISNULL(MAX(CardID), -1) AS MaxCard
FROM dbo.Transactions)
【讨论】:
如果 TRANSACTIONS 表中根本没有记录,CTE 会返回 -1 吗? @OMG 小马:是的CREATE TABLE OMG (Ponies int); SELECT MAX(Ponies) FROM OMG
@OMG Ponies:无耻塞...***.com/questions/2552086/…
如上面的 SQL 写的,我得到了关于无法找到 MaxCard 的错误,即使我将 cHighestCard.MaxCard 添加到第二个 SELECT 的列列表中。【参考方案2】:
由于您提到您尝试将其创建为视图,这意味着您可能希望在另一个查询中使用结果。如果这是真的,我会把它设为table-valued function。
【讨论】:
如果没有至少一个参数,我似乎无法让表值函数工作。我真的一点也不想要。可以这样做,还是我应该只定义一个空白并设置默认值? 它必须是一个多语句 TVF,它是优化器的黑匣子 ***.com/questions/510743/…【参考方案3】:这是一个存储过程。它很容易使用。只需告诉管理工作室您要创建一个新程序,它甚至会为您构建所有基本框架语法。
http://msdn.microsoft.com/en-us/library/ms345415.aspx
【讨论】:
【参考方案4】:您可以将其重新编码为带有 COALESCE 的子查询以避免重复输入:
SELECT ....
FROM ....
WHERE dbo.STAUpload.code > COALESCE(
(Select max(cardId) from dbo.transactions),-1)
然后它就变成了一个视图。
【讨论】:
这仍然会执行两次。 (connect.microsoft.com/SQLServer/feedback/details/336002/…) @Martin, @Ken Downs:那时我会考虑 ISNULL。例如,如果 cardID 是 smallint,那么 .code 可能会因为 COALESCE 数据类型处理而被强制转换为 int(尽管优化器可能将 -1 视为 smallint)【参考方案5】:您可以在存储过程中执行此操作。只需传入您的变量,它就会按需要工作。
在 msdn 或在线书籍上快速搜索和查看存储过程。
【讨论】:
【参考方案6】:这可能只是一个简单的视图,无需使用 CTE。子查询中针对 SELECT MAX 的 ISNULL 可能更容易解释将 ISNULL 内联到子查询中。
CREATE VIEW Q_SO
AS
SELECT Uploads.*, Transactions.*
FROM Uploads
LEFT OUTER JOIN dbo.Transactions
ON dbo.Uploads.Code = dbo.Transactions.CardID
WHERE (Uploads.Code > ISNULL((SELECT MAX(CardID) FROM dbo.Transactions),-1))
作为无参数的表值函数
CREATE FUNCTION Q_FN() RETURNS TABLE AS RETURN
SELECT Uploads.*, Transactions.*
FROM Uploads
LEFT OUTER JOIN dbo.Transactions
ON dbo.Uploads.Code = dbo.Transactions.CardID
WHERE (Uploads.Code > ISNULL((SELECT MAX(CardID) FROM dbo.Transactions),-1))
【讨论】:
【参考方案7】:只需将初始化 @HighestTansaction
的子查询交叉连接到您的主查询,如下所示:
SELECT Uploads.*, Transactions.*
FROM Uploads LEFT OUTER JOIN
dbo.Transactions ON dbo.Uploads.Code = dbo.Transactions.CardID CROSS JOIN
(SELECT ISNULL(MAX(CardID),-1) FROM dbo.Transactions) m(HighestTransaction)
WHERE (Uploads.Code > m.HighestTransaction)
【讨论】:
以上是关于视图、存储过程或表定义函数的主要内容,如果未能解决你的问题,请参考以下文章