SQL - 写入查询,字段名称和表名存储在表中?

时间:2014-03-27 20:45:29

标签: sql sql-server-2008 while-loop dynamic-sql

我在保险公司工作并创建自定义应用程序。当我们对策略应用coverage时,它将存储在具有Limit,Deductible和Premium字段的表中。但是,有许多覆盖范围不符合规范。它们使用Limit,Deductible和Premium的不同字段,甚至存储在不同的表中。 (不要问为什么,甚至不试图理解他们仍在这样做的事实,所以我需要留下逻辑以允许这样的额外覆盖。)他们选择的字段也没有押韵或理由漂浮不定。

因此,我们决定创建“LookUp”表,这些表将存储覆盖所需的所有信息。这避免了许多连接 - 我们遇到了应用程序的速度和性能问题。

我需要找到一种方法将所有这些字段预先填充到表格中。我希望性能方面的最佳选择。这将最终成为一个夜间工作 - 所以当我们收到新的数据快照时,我们将运行此查询并预填充/更新表的值。

以下是我的表的示例,它包含Coverage名称(Coverage),表(File)以及Limit,Deductible和Premium的字段。 PolicyNum字段是LOB + Policy + Module的串联。我需要所有这三个领域加入政策。我想使用表格,因为它们将添加新的覆盖范围。请记住,我创建了这个表,因此可以添加更多字段。

这是我的表格的创建脚本 - 我从Excel电子表格填写它,所以使所有字段nVarChar(255),以便该过程顺利运行:

USE [PolicySummary]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Coverage](
    [CoverageID] [int] IDENTITY(1,1) NOT NULL,
    [LOB] [nvarchar](255) NULL,
    [Coverage] [nvarchar](255) NULL,
    [Description] [nvarchar](255) NULL,
    [File] [nvarchar](255) NULL,
    [Limit] [nvarchar](255) NULL,
    [Deductible] [nvarchar](255) NULL,
    [Premium] [nvarchar](255) NULL,
    [IsMultLimit] [bit] NULL,
    [IsMultDeductible] [bit] NULL,
    [IsMultPremium] [bit] NULL,
    [InsuranceLine] [nvarchar](255) NULL,
    [PolicyNum] [nvarchar](255) NULL,
 CONSTRAINT [PK_Coverage] PRIMARY KEY CLUSTERED 
(
    [CoverageID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,     ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

因此,简而言之,政策可能具有BP0713的覆盖范围。然后我看看这个表,看看我需要运行以下查询:     选择BYAGVA作为限制,BYPPTX作为免赔额,BYA3VA作为Premium来自ASBYCPP WHERE BYARTX + BYASTX + BYADNB = @PolNum

该表包含表名,3个字段以及策略号的串联。

目前,我正在遍历策略中的每个coverage,并在WHLIE循环中一次选择一个值。工作,但它很慢,我打了很多次只是为了打开应用程序(每个政策将运行多个单位,因此将为每个单位运行)。

SELECT @SQL = N'SELECT @Limit=' + ISNULL(Limit, '''''') + N',@Deductible=' +     ISNULL(Deductible, '''''') + N',@Premium=' + ISNULL(Premium, '''''') + N' FROM PHI_PIJ.dbo.'     + [File] + N' WHERE ' + PolicyNum + N' = ''' + @PolNum +'''' + N' AND ' + @CovField +     N'='''+Coverage +''''
FROM PolicySummary.dbo.Coverage 
WHERE Coverage = @Coverage 
AND LOB = @LOB           

EXEC sp_executesql @SQL, N'@Limit nVarChar(255) output,@Deductible nVarChar(255)         output,@Premium nVarChar(255) output', @Limit output, @Deductible output, @Premium output

INSERT INTO #OptCov2 VALUES(@Coverage, @Description, @LOB, @Limit, @Deductible,     @Premium)

我可以帮助找到每晚填充“Lookup”表的方法,所以我所要做的就是     SELECT Limit,Deductible,PREMIUM from CoverageLookUp WHERE PolicyNum = @PolicyNum

我正在使用Microsoft SQL Server Management Studio。

这是我到目前为止所得到的。运行前1000个记录需要将近4分钟,并且总共有614,497条记录要运行。

SELECT @SQL = N'SELECT @Limit=' + ISNULL(Limit, '''''') + N',@Deductible=' +   ISNULL(Deductible, '''''') + N',@Premium=' + ISNULL(Premium, '''''') + N'     FROM PHI_PIJ.dbo.ASBYCPP' + N' WHERE ' + PolicyNum + N' = ''' + @PolicyKey +'''' + N' AND BYAOTX' + N'='''+Coverage +''''
FROM PolicySummary.dbo.Coverage 
WHERE Coverage = @Coverage 
AND LOB = 'BOP'         

EXEC sp_executesql @SQL, N'@Limit nVarChar(255) output,@Deductible nVarChar(255) output,@Premium nVarChar(255) output', @Limit output, @Deductible output, @Premium output              

UPDATE PolicySummary.dbo.CoverageLkup
SET Limit = @Limit, Deductible = @Deductible, Premium = @Premium
WHERE CovAbbrev = @Coverage
AND PolicyKey = @PolicyKey

2 个答案:

答案 0 :(得分:0)

我认为你是从错误的角度来看待这件事。我会将您的计划声明为“创建一个映射表,您使用动态SQL路线图来处理源数据”。相反,我认为您应该将来自不同表的源数据复制到单个主查找表中。

虽然这将“复制”数据,但它会带来更高效的查找效果。

* copy:我最初编写了replicate,但我不认为Replication是正确的技术。它可能是可能的,但它不是复制的预期用例。

你想要一个不同的排序ETL,可能是非常简单的工作或SSIS(甚至是触发器),让你的查找主人与所有单个部分保持同步。

请注意,这一点没有意义。或者,如果我似乎错过了什么。

答案 1 :(得分:0)

我意识到这可能不是你所拥有的,但希望这可以指出你正确的方向。你肯定希望避免循环,特别是为每个策略做这件事。

从易于更新的角度来看,我建议如下:

这是包含表名和字段名的表。它将用于构建您的select语句。这里每张表只能有1条记录。

create table tableref (
  tablename nvarchar(255), 
  lobfield nvarchar(255), 
  policyfield nvarchar(255), 
  modulefield nvarchar(255),
  limitfield nvarchar(255), 
  deductfield nvarchar(255),
  premiumfield nvarchar(255))

现在创建select语句,从tableref

中拉出表中的所有数据
declare @sql nvarchar(max) = '', @unionall nvarchar(50) = ''
select @sql = @sql + @unionall 
    + ' select ' + lobfield + '+' + policyfield + '+' + modulefield + ' as policynumber, ' 
    + limitfield + ' as limit, ' 
    + deductfield + ' as deduct, ' 
    + premiumfield + ' as premium '
    + ' from ' + tablename
  , @unionall = ' union all '
from tableref

最后但并非最不重要的是,将记录插入查找表

select @sql = 'insert into lookuptable (policynum, limit, deduct, premium) ' + @sql
exec (@sql)

要微调,请在适当的位置添加索引。此外,此解决方案将在@sql中的8000个字符后中断,因此根据您的具体情况,您可能需要将其分解。