4

我是 SQL Server 2005 存储过程的初学者。我似乎无法让它按要求工作。

我有一个 sp 从名为annot. @caseid分配给列的值,src_caseid并且在表中可以有多个引用 ( ref_caseid) 或没有annot。我想根据我使用 INNER JOIN 所做court的表中的列设置条件并设置正确的 shepardsflag 。case

基本上是这样的场景:

  • annot-ref_caseid, src_caseid, annotation
  • case-caseid, court

INNER JOIN 的结果集示例ref_caseid = caseid如下:

ref_caseid   src_caseid   annotation    court
  17334         17338        Refd       high court
  17600         17338        Foll       federal court
  18271         17338        Foll       federal court
  43220         17338        Not Foll   supreme court

设置条件:

从记录集中,如果federal court存在,它应该只取federal court. 如果发现否federal court,则将采取其他具有其他法院价值的案件。

为此,我为federal court计数设置了一个计数器。但似乎 SQL 只读取最后一行并@courtFC根据它设置值。我已经尝试过order by,但似乎效果不佳。

从上面的示例中,案例 17338 的最终 shepardsflag 值应为 = 3(Foll),因为它应仅采用“联邦法院”行并忽略其余行。

但目前的结果是 shepardsflag = 2 ; 这是错误的

我希望我解释清楚。

有人可以帮助我正确的逻辑吗?我应该创建一个临时表吗?提前致谢。

脚本:

ALTER PROCEDURE [dbo].[spUpdateShepardsFlags] @caseid int = null AS
begin
declare @Shep int
declare @ref_caseid int
declare @court int
declare @courtFC int
declare @annot int

if @caseid is not null
   begin
      select @court = b.court, @ref_caseid = a.ref_caseid, @annot = a.annotation
         from cba_annot a inner join cbm_case b on a.ref_caseid = b.caseid 
         where a.src_caseid = @caseid

      if @court is not null
        begin
           if @court = 'MYFC'
              set @courtFC = @courtFC + 1
           if @court <> 'MYFC'
              SET @courtFC = @courtFC + 0
            PRINT 'The @courtFC counter : ' + CAST(@courtFC AS CHAR) 
        end

        if @court is not NULL 
        begin
          if @courtfc > 0
           begin 
             if exists(select a.ref_caseid, b.court, a.annotation, a.src_caseid from 
                       cba_annot a inner join cbm_case b on a.ref_caseid = b.caseid)
                begin
                   if exists(select src_caseid from cba_annot where (annotation like '%Refd%'
                      or annotation like '%Comp%')
                      and src_caseid = @caseid)
                      set @Shep = 4

                   if exists(select src_caseid from cba_annot where (annotation like '%Foll%'
                      or annotation like '%Aff%')
                      and src_caseid = @caseid)
                      set @ShepFC = 3

                    update cbm_case
                    set shepardsflag = @shep
                    where caseid=@caseid
                end
            end

          else -- if @courtFC = 0
            begin --new
             if exists(select a.ref_caseid, b.court, a.annotation, a.src_caseid from 
                       cba_annot a inner join cbm_case b on a.ref_caseid = b.caseid)
                begin
                   if exists(select src_caseid from cba_annot where (annotation like '%Refd%'
                      or annotation like '%Comp%')
                      and src_caseid = @caseid)
                      set @Shep = 4

                   if exists(select src_caseid from cba_annot where (annotation like '%Foll%'
                      or annotation like '%Aff%')
                      and src_caseid = @caseid)
                      set @Shep = 3

                   if exists(select src_caseid from cba_annot where (annotation like '%Not Foll%'
                      or annotation like '%Dist%')
                      and src_caseid = @caseid)
                      set @Shep = 2

                    update cbm_case
                    set shepardsflag = @shep
                    where caseid=@caseid
                end

          end -- new
      end
  else  --- if court is NULL -- case not referred by any other case
        update cbm_case
        set shepardsflag = 5
        where caseid=@caseid
  end 

else -- if caseid is null

-- other condition
4

1 回答 1

2

您对 SQL 的理解存在一些实际问题,我严重怀疑临时表是否相关。

1)变量被初始化为 null,但这似乎并没有让你大吃一惊。(@courtFC + 0 不会以您可能想的方式评估您。)

2)你做任务的方式取决于顺序,最后一个赢了,就像你注意到的那样。而不是说:

select @court = b.court, ...

你可以使用这个:

select @courtFC = count(b.court) ... where b.court = 'federal court'

您似乎也正在尝试编写一个循环,我认为这是您困惑的另一部分。SQL 是关于集合的,一次对多行进行操作。

3)内部块中的所有 EXISTS 子查询都缺少相关 caseid 上的过滤器。

您的方法实际上可能仅适用于这些更改。

我在这里的版本不是为了使事情复杂化,但我担心你会遇到麻烦。这是一个基于集合的解决方案,它确实是一种更自然的方式。

if @caseid is not null /* short-circuit the update, but probably not necessary */
update cbm_case
set shepardsflag = coalesce(
    (
    select
        case
            max( /* highest precendence wins */
                case /* map annotations by precedence i.e. */
                     /* if there are multiple annotations, */
                     /* which one takes priority */
                    when a.annotation in ('Refd', 'Comp')     then 'P1'
                    when a.annotation in ('Foll', 'Aff')      then 'P2'
                    when a.annotation in ('Not Foll', 'Dist') then 'P3'
                    else cast(0/0 as char(2)) /* error, I think */
                end
            )
            when 'P1' then 4 /* translate back to shepardsflag */
            when 'P2' then 3
            when 'P3' then 2
        end
    from
        cba_annot as a inner join cbm_case as refcase
            on refcase.caseid = a.ref_caseid
    where
        a.src_caseid = cbm_case.caseid
        and (
            cbm_case.court <> 'federal court'  /* all if src case not federal */
            or refcase.court = 'federal court' /* always get federal */
        )
    ),
    5
)
where caseid = @caseid;

编辑 2 忽略我在 3) 中的评论。再看一遍,我认为由于括号和换行符而误读了 OP 的代码。

编辑 3 修复了由于第一行中缺少 @ 字符而导致的错误。

于 2012-07-08T04:41:44.597 回答