DB2 SQL 在具有动态列的 Select 语句中清理数据
DB2 SQL Scubbing Data in a Select Statement with dynamic columns
我们当然有一个使用 DB2 的 AS400,我需要将客户数据复制到一个新位置进行分析,但必须擦除它以保护敏感信息。我用大约 30-40 张桌子来做这件事。存储过程越来越大…
无论如何,举个简单的例子,假设列的数据看起来有点像这样,在第 2 行中,复制数据的结果:
Col1 | Col2 | Name | Sex | SS# | Age | Col7 | Col8 |
______________________________________________________________________________________________
* | * | Case when Sex = F, | * | 111111111 | * | * | * |
| then Jane Doe else |
| John Smith end |
我的第一次尝试是进行大量插入然后更新,例如:
Insert into New_Table (Select * from Old_Table) ;
Update New_Table
set Name = ( Case when Sex = ‘F’ then ‘Jane Doe’ else ‘John Smith’ End),
SS# = 111111111 ;
问题在于,在表上的一百万行、200 列和触发器上,插入语句很快,但更新速度慢得令人痛苦——长达数小时。因此,在 Stack 的帮助下,我尝试了以下操作:
Insert into New_Table (Select Col1, Col2,
(Case when Sex = ‘F’ then ‘Jane Doe’ else ‘John Smith’ End),
Sex, 111111111, Age, Col7, Col8)
像冠军一样工作 - 感谢 Stack 团队!!
现在,我有另一个问题。我有一些开发人员有向这些表中添加列的恶习,而我不在他们的团队中。这些表有 200 列,当我 运行 出错时,当我必须找到新列时,修改可能很有趣
所以我试图想出一种方法来动态构建 SQL 语句并执行它,因此列是灵活的。当然,它会在构建它的语句上再增加一秒钟,但是与发生错误时的劳动时间相比,这是非常值得的。
我正在考虑使用列查找之类的东西,然后只替换成我想要的列,构建 SQL 语句,然后调用它的 Exec。我只是想不出该怎么做。至于构建语句,与查询的 运行 时间相比,它可能需要一些时间。例如,我可以拉列:
Select COLUMN_NAME from Sysibm.columns where tbname = 'old_table' AND table_schema = ‘MySchema’.
也许我可以把它放到一个变量中,然后搜索我知道的列(名称、ss#)并替换它们,然后构建一个 SQL 语句并执行它?列的 select 语句的结果(上面)虽然不适合我需要的逗号分隔列表。据我所知。
有人有想法吗?
提前致谢。
这个:
Insert into New_Table (Select * from Old_Table)
在生产代码中从来都不是一个好主意。您应该始终明确列出所需的列。
Insert into
New_Table (Col1, Col2, Name, Sex, SS#, Age, Col7, Col8)
(Select Col1, Col2,
(Case when Sex = ‘F’ then ‘Jane Doe’ else ‘John Smith’ End),
Sex, 111111111, Age, Col7, Col8)
添加到 table 的任何新列都应该有适当的默认值。现在,添加列时您的流程不会中断。
当然,您清理后的数据将具有新列的默认值,这可能是也可能不是问题。因此,复制数据是唯一一个例外,它证明了永远不要在生产中使用 SELECT *
的规则。
您使用 syscolumns 的想法很好,还有 List Fields (QUSLFLD) API。您将不得不在循环中一次构建一列逗号分隔列表。
如果是我,我会建立两个列表。一个用于我不必擦洗的任何列,一个用于要擦洗的列。同时,您构建替代品
select 文字。这将使您的声明像这样构建:
wSQL = 'insert into new_table (' + wNonSrub + ',' + wSrub + ')'
+ ' (select ' + wNonScub + ',' + wReplacement
+ ' from old_table' + ')';
另一个可能的想法...在 table 上放置一个 Insert/Update 之前的触发器,该触发器应该具有已清理的数据。该触发器可以在数据写入 table 之前清理数据。老实说,我最喜欢这个主意。即使有人手动复制数据而不是使用您正在构建的过程,它也会确保数据被擦除。
加快 AS400 上的插入速度。您可能在要插入记录的 table 上构建了许多逻辑文件。将这些逻辑文件更改为 REBLD(*DELAY)
CHGLF mylib/mylogicalfile rebld(*delay)
唯一的副作用是第一个人,并且只有第一个人在任何给定的一天打开文件,在重建访问路径时可能需要等待几秒钟。
我们当然有一个使用 DB2 的 AS400,我需要将客户数据复制到一个新位置进行分析,但必须擦除它以保护敏感信息。我用大约 30-40 张桌子来做这件事。存储过程越来越大…
无论如何,举个简单的例子,假设列的数据看起来有点像这样,在第 2 行中,复制数据的结果:
Col1 | Col2 | Name | Sex | SS# | Age | Col7 | Col8 |
______________________________________________________________________________________________
* | * | Case when Sex = F, | * | 111111111 | * | * | * |
| then Jane Doe else |
| John Smith end |
我的第一次尝试是进行大量插入然后更新,例如:
Insert into New_Table (Select * from Old_Table) ;
Update New_Table
set Name = ( Case when Sex = ‘F’ then ‘Jane Doe’ else ‘John Smith’ End),
SS# = 111111111 ;
问题在于,在表上的一百万行、200 列和触发器上,插入语句很快,但更新速度慢得令人痛苦——长达数小时。因此,在 Stack 的帮助下,我尝试了以下操作:
Insert into New_Table (Select Col1, Col2,
(Case when Sex = ‘F’ then ‘Jane Doe’ else ‘John Smith’ End),
Sex, 111111111, Age, Col7, Col8)
像冠军一样工作 - 感谢 Stack 团队!!
现在,我有另一个问题。我有一些开发人员有向这些表中添加列的恶习,而我不在他们的团队中。这些表有 200 列,当我 运行 出错时,当我必须找到新列时,修改可能很有趣
所以我试图想出一种方法来动态构建 SQL 语句并执行它,因此列是灵活的。当然,它会在构建它的语句上再增加一秒钟,但是与发生错误时的劳动时间相比,这是非常值得的。
我正在考虑使用列查找之类的东西,然后只替换成我想要的列,构建 SQL 语句,然后调用它的 Exec。我只是想不出该怎么做。至于构建语句,与查询的 运行 时间相比,它可能需要一些时间。例如,我可以拉列:
Select COLUMN_NAME from Sysibm.columns where tbname = 'old_table' AND table_schema = ‘MySchema’.
也许我可以把它放到一个变量中,然后搜索我知道的列(名称、ss#)并替换它们,然后构建一个 SQL 语句并执行它?列的 select 语句的结果(上面)虽然不适合我需要的逗号分隔列表。据我所知。
有人有想法吗?
提前致谢。
这个:
Insert into New_Table (Select * from Old_Table)
在生产代码中从来都不是一个好主意。您应该始终明确列出所需的列。
Insert into
New_Table (Col1, Col2, Name, Sex, SS#, Age, Col7, Col8)
(Select Col1, Col2,
(Case when Sex = ‘F’ then ‘Jane Doe’ else ‘John Smith’ End),
Sex, 111111111, Age, Col7, Col8)
添加到 table 的任何新列都应该有适当的默认值。现在,添加列时您的流程不会中断。
当然,您清理后的数据将具有新列的默认值,这可能是也可能不是问题。因此,复制数据是唯一一个例外,它证明了永远不要在生产中使用 SELECT *
的规则。
您使用 syscolumns 的想法很好,还有 List Fields (QUSLFLD) API。您将不得不在循环中一次构建一列逗号分隔列表。
如果是我,我会建立两个列表。一个用于我不必擦洗的任何列,一个用于要擦洗的列。同时,您构建替代品 select 文字。这将使您的声明像这样构建:
wSQL = 'insert into new_table (' + wNonSrub + ',' + wSrub + ')'
+ ' (select ' + wNonScub + ',' + wReplacement
+ ' from old_table' + ')';
另一个可能的想法...在 table 上放置一个 Insert/Update 之前的触发器,该触发器应该具有已清理的数据。该触发器可以在数据写入 table 之前清理数据。老实说,我最喜欢这个主意。即使有人手动复制数据而不是使用您正在构建的过程,它也会确保数据被擦除。
加快 AS400 上的插入速度。您可能在要插入记录的 table 上构建了许多逻辑文件。将这些逻辑文件更改为 REBLD(*DELAY)
CHGLF mylib/mylogicalfile rebld(*delay)
唯一的副作用是第一个人,并且只有第一个人在任何给定的一天打开文件,在重建访问路径时可能需要等待几秒钟。