使用动态表名验证字段

Posted

技术标签:

【中文标题】使用动态表名验证字段【英文标题】:Validating fields with dynamic table names 【发布时间】:2018-10-20 17:53:54 【问题描述】:

我有 N 个这样的表:

foo_1_data
(
    id int,
    some_foo_data_1 varchar(100),
    some_foo_data_2 char(5)
)

foo_2_data
(
    id  int,
    some_foo_data_1 varchar(100),
    some_foo_data_2 char(5)
)

bar_1_data
(
    id int,
    some_bar_data_1 decimal(10,2),
    some_bar_data_2 datetime
)

bar_2_data
(
    id int,
    some_bar_data_1 decimal(10,2),
    some_bar_data_2 datetime
)

这些表基于不同的数据 - foo_databar_data - 并且是用户生成的,并且有一个 ID - foo_N_databar_N_data - 设置。

现在我想通过存储过程对这些表上的记录进行验证,以在接收端遵循某些我们无法控制的业务规则。

例子:

    some_foo_data_1 是一个 varchar(100) 是一个名称,在我们的系统中它可以是 介于 0 到 100 个字符之间,但在接收端它需要是 2 到 70 个字符。 some_bar_data_1 是小数(10.2),需要介于 0 和 100(假设是一个百分比)

我们尝试并实现了名为 sp_rule_name 的存储过程,它采用原始表和列并通过 Dynamic SQL 对其进行验证,如下所示:

EXEC('SELECT ' + @column_to_validate + ' FROM ' + @table_to_validate + ' WHERE ...')

这会在不同的验证过程之间创建可重复使用的代码(每个不同的数据集一个 - 一个用于foo_data,一个用于bar_data)但由于@987654334 的混合,代码难以理解和维护@ 和 Dynamic SQL。我们还尝试在字段上使用functions,但由于性能缓慢而放弃了它。

是否有一种有效且可重复使用的方法来验证来自动态表格的数据?

注意:我们知道foobar 的表结构是什么样的,但我们不知道N 值,所以我们不能直接调用它。

【问题讨论】:

让您的用户在您的数据库中运行 DDL 语句在大多数情况下都是不好的做法,更不用说安全隐患了。如果可能的话,我建议重新考虑整个方法。 另外,您真的在使用 2005 版本吗?如果可能,您应该至少将其升级到 2012 版本 (since even 2008 is now on extended support ending next year) 【参考方案1】:

曾经遇到过类似的情况,我不得不依靠动态 SQL 来完成工作。但是对其进行故障排除甚至阅读它都是一种痛苦。 我做了一个小改动,这有助于解决故障排除/阅读问题,特别是如果它只是基础表上的 SELECT

See live demo

create proc sp_rule_name  @tblName varchar(100)
as 
begin
    declare @sql varchar(max);
    set @sql =' CREATE VIEW tempView  AS  SELECT * FROM '+ @tblName+ ' ;'
    exec (@sql)
    -- after this normal SQL syntax using tempView object for all sort of validations. No need for dynamic SQL
    select * from tempView;
end
go

create table foo_1_data (
    id int,
    some_foo_data_1 varchar(100),
    some_foo_data_2 char(5)
);
insert into foo_1_data values
(1,'345453','56666');



execute sp_rule_name N'foo_1_data';

【讨论】:

以上是关于使用动态表名验证字段的主要内容,如果未能解决你的问题,请参考以下文章

[转]MyBatis动态传入表名,字段名参数的解决办法

mybatis中怎么动态的获取表的字段

MyBatis动态传入表名,字段名参数的解决办法

mybatis动态接收表名,字段名,字段值

经验与坑MyBatis+MySQL 返回格式化日期以及动态表名和字段名

oracle 动态传入表名,怎么做? 高手指点