(T)Sql 视图包含太多业务逻辑
A (T)Sql view containing too much business logic
我有一个 TSQL 视图。除了一些列之外,它是非常基本的,因为它只是简单地进行一些连接,然后将所有内容粘合在一起以呈现应有的漂亮视图。然而,少数不那么简单的列使得视图代码很难扩展,现在新的需求进来使复杂的列的业务逻辑失效。
无需过多赘述,我的数据库中有一个 table:
tblEmployment
这由 "employments" 行组成。每次连续 任何 列,对于给定的就业变化(假设 employmentTitle
变化),那么 current行被推入另一个 table tblEmploymentHistory
,tblEmployment
中的行被更改,因此它包含最新的 employmentTitle
.
本质上,视图所做的是尝试将 tblEmploymentHistory
上的 tblEmployment
与唯一的 EmploymentIdentifier
连接起来,这是有道理的。
视图中更复杂的列将尝试通过对它连接在一起的行(即从 tblEmployment and tblEmploymentHistory
)进行各种计算来计算一个数字(每行 elapsedTime
)。为了获得经过的时间,它根据规定的业务逻辑执行计算,例如历史记录中只有特定的日期时间列 table 应该计入总的 elapsedTime 并且只有当该行中的其他列设置为特定值等时才应该这样做
现在有了新的需求,业务逻辑比以前复杂了很多。我发现很难扩展视图以包含它,因为它变得非常混乱,我觉得这可以在其余业务逻辑也驻留的应用程序层中完成得更有条理!
是否 "correct" 废弃视图并将其移动到我的应用程序的应用层?显然,拥有视图的好处是速度很快,并且在代码中计算大约 100.000 行将需要一些时间。但是,可以通过过滤掉行来优化它,使数字在 10.000 左右。
解决这个问题的 "standard" 和最干净的方法是什么?
答案取决于几件事。首先,确保数据库正在执行基于集合的工作。如果您开始使用游标(一般来说)或某种循环,最好将其放在应用程序中。关系数据库以这种方式工作效率不高。我要考虑的另一件事是您工作环境的标准是什么?您所在的数据库中是否还维护着其他东西?如果是这样,您可能希望保持一致。
最终,无论returns那些最有效且不影响其他查询的结果,都应该是答案。
正如我所承诺的那样,我将为您提供一个 UDF 方法的示例:
在我的一个项目中,我将其与 40 多个不同的分层结构 UDF 一起使用,以获得包含近 1000 列的结果集。
CREATE TABLE dbo.TestTable(Col1 INT,Col2 INT,Col3 INT);
INSERT INTO dbo.TestTable VALUES(1,2,3),(4,5,6),(7,8,9);
GO
CREATE FUNCTION dbo.TestFunc(@Prm1 INT,@Prm2 INT)
RETURNS TABLE
AS
RETURN
SELECT @Prm1 AS Func_Prm1 --use names, which will be unique in any usage, this makes things much easier!
,@Prm2 AS Func_Prm2
,@Prm1 * @Prm2 AS Func_Calculated;
GO
--This would be your simple VIEW, consisting of any columns you can easily get
SELECT *
FROM dbo.TestTable
--This is how you join the "buiness logic" to your view
CROSS APPLY dbo.TestFunc(TestTable.Col1,TestTable.Col2) AS func
DROP TABLE dbo.TestTable;
GO
DROP FUNCTION dbo.TestFunc;
GO
我有一个 TSQL 视图。除了一些列之外,它是非常基本的,因为它只是简单地进行一些连接,然后将所有内容粘合在一起以呈现应有的漂亮视图。然而,少数不那么简单的列使得视图代码很难扩展,现在新的需求进来使复杂的列的业务逻辑失效。
无需过多赘述,我的数据库中有一个 table:
tblEmployment
这由 "employments" 行组成。每次连续 任何 列,对于给定的就业变化(假设 employmentTitle
变化),那么 current行被推入另一个 table tblEmploymentHistory
,tblEmployment
中的行被更改,因此它包含最新的 employmentTitle
.
本质上,视图所做的是尝试将 tblEmploymentHistory
上的 tblEmployment
与唯一的 EmploymentIdentifier
连接起来,这是有道理的。
视图中更复杂的列将尝试通过对它连接在一起的行(即从 tblEmployment and tblEmploymentHistory
)进行各种计算来计算一个数字(每行 elapsedTime
)。为了获得经过的时间,它根据规定的业务逻辑执行计算,例如历史记录中只有特定的日期时间列 table 应该计入总的 elapsedTime 并且只有当该行中的其他列设置为特定值等时才应该这样做
现在有了新的需求,业务逻辑比以前复杂了很多。我发现很难扩展视图以包含它,因为它变得非常混乱,我觉得这可以在其余业务逻辑也驻留的应用程序层中完成得更有条理!
是否 "correct" 废弃视图并将其移动到我的应用程序的应用层?显然,拥有视图的好处是速度很快,并且在代码中计算大约 100.000 行将需要一些时间。但是,可以通过过滤掉行来优化它,使数字在 10.000 左右。
解决这个问题的 "standard" 和最干净的方法是什么?
答案取决于几件事。首先,确保数据库正在执行基于集合的工作。如果您开始使用游标(一般来说)或某种循环,最好将其放在应用程序中。关系数据库以这种方式工作效率不高。我要考虑的另一件事是您工作环境的标准是什么?您所在的数据库中是否还维护着其他东西?如果是这样,您可能希望保持一致。
最终,无论returns那些最有效且不影响其他查询的结果,都应该是答案。
正如我所承诺的那样,我将为您提供一个 UDF 方法的示例: 在我的一个项目中,我将其与 40 多个不同的分层结构 UDF 一起使用,以获得包含近 1000 列的结果集。
CREATE TABLE dbo.TestTable(Col1 INT,Col2 INT,Col3 INT);
INSERT INTO dbo.TestTable VALUES(1,2,3),(4,5,6),(7,8,9);
GO
CREATE FUNCTION dbo.TestFunc(@Prm1 INT,@Prm2 INT)
RETURNS TABLE
AS
RETURN
SELECT @Prm1 AS Func_Prm1 --use names, which will be unique in any usage, this makes things much easier!
,@Prm2 AS Func_Prm2
,@Prm1 * @Prm2 AS Func_Calculated;
GO
--This would be your simple VIEW, consisting of any columns you can easily get
SELECT *
FROM dbo.TestTable
--This is how you join the "buiness logic" to your view
CROSS APPLY dbo.TestFunc(TestTable.Col1,TestTable.Col2) AS func
DROP TABLE dbo.TestTable;
GO
DROP FUNCTION dbo.TestFunc;
GO