【问题标题】:insert based on value in first row根据第一行中的值插入
【发布时间】:2016-01-30 01:22:50
【问题描述】:

我有一个固定文件,我将其导入到一个列中,其中的数据类似于您在下面看到的:

ABC$        WC        11683                                    
11608000163118430001002010056788000000007680031722800315723      
11683000486080280000002010043213000000007120012669100126691      
ABC$        WC                         000000020000000148000     
ABC$        WC        11683                                    
1168101057561604000050200001234000000027020023194001231940      
54322010240519720000502000011682000000035640006721001067210      
1167701030336257000050200008765000000023610029066101151149      
11680010471244820000502000011680000000027515026398201263982

我想将此数据拆分并插入到另一个表中,但只要“11683”等于另一个表中的列值 + 1,我就想这样做。然后我将增加该值(这里看不到)。

我尝试了以下方法:

declare @blob as varchar(5) 
declare @Num as varchar(5)

set @blob = substring(sdg_winn_blob.blob, 23,5)
set @Num = (Cnum.num + 1)

IF @blob = @Num
INSERT INTO SDG_CWF
    (
        GAME,SERIAL,WINNER,TYPE
    )
SELECT convert(numeric, substring(blob,28, 5)),convert(numeric, substring(blob, 8, 9)),
        (Case when (substring(blob, 6,2)='10') then '3' 
              when (substring(blob, 6,2)='11') then '4' 
              else substring(blob, 7, 1)
         End),
        (Case when (substring(blob, 52,2)='10') then '3' 
              when (substring(blob, 52,2)='11') then '4' 
              else substring(blob, 53, 1)
         End)

FROM sdg_winn_blob
WHERE blob not like 'ABC$%'
else
print 'The Job Failed'

插入工作正常,直到我尝试检查位置 (23, 5) 处的数字是否与 Cnum 表中的数字相同。我得到错误:

Msg 4104, Level 16, State 1, Line 4
The multi-part identifier "sdg_winn_blob.blob" could not be bound.
Msg 4104, Level 16, State 1, Line 5
The multi-part identifier "Cnum.num" could not be bound.

【问题讨论】:

  • 您是否尝试过包含架构 dbo.Cnum.num & dbo.sdg_winn_blob.blob

标签: tsql sql-server-2005


【解决方案1】:

看起来您可能已经习惯了程序化、面向对象的编码风格。 SQL Server 希望你的想法完全不同......

这一行:

set @blob = substring(sdg_winn_blob.blob, 23,5)

因为 SQL 孤立地解释它而失败。就在那一行中,您没有告诉 SQL 对象 sdg_winn_blob 是什么,也没有告诉 SQL 它的成员 blob

由于这些东西是数据库表/列,它们只能作为包含 FROM 子句的查询的一部分来访问。是 FROM 告诉 SQL 这些东西在哪里。

因此,您需要将该行(以及下一行)替换为以下内容:

Select @blob = substring(sdg_winn_blob.blob, 23,5)
From sdg_winn_blob
Where... 

此外,据我所知,您的整个方法在概念上是迭代的:您正在考虑依次查看每一行、处理它,然后移动到下一行。 SQL 确实提供了执行此操作的工具(您在这里没有使用过),但它们很少是最好的解决方案。 SQL 更喜欢(并针对)基于集合的 方法进行了优化:设计一个一次性对所有行进行操作的查询。

就目前而言,我认为您的查询永远不会完全按照您的意愿行事,因为您期望 SQL 不遵循的迭代行为。

如果您想“像 SQL Server 一样思考”,您需要解决此问题的方法是构造(仅使用 SELECT 类型查询)一组具有来自标题行的 '11683' 类型值的行,应用于每个您要插入到SDG_CWF 的相应“数据”行。

然后,您可以使用 SQL JOIN 将此行集链接到您的 Cnum 表,并确定每一行是否满足 Cnum 中所需的条件。然后可以将这组行插入SDG_CWF。不涉及变量或 IF 语句(它们在 SQL 中的必要性远没有某些人想象的那么频繁)。

对此有多种可能的方法,但都不是非常简单(除非我遗漏了一些明显的东西)。所有这些都需要您将逻辑分解为多个步骤,获取初始数据集(只是一个 blob 列)并将其转换为更接近您需要的内容,然后重复。您可能想自己解决这个问题,但如果没有,我在this SQLFiddle 中设置了一个示例。

我并不声称该示例是最快或最简洁的(它不是),但希望它能够说明我的意思,即按照 SQL 希望您思考的方式思考。该网站背后的 SQL 引擎使用的是 SQL 2008,但我提供的解决方案在 2005 上应该同样有效。如果您可以访问 2012 或更高版本,则可能有更好的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 2013-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多