zoukankan      html  css  js  c++  java
  • 如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?

    如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?(2006-12-14 09:25:36)

    与这个问题具有相同性质的其他描述还包括:
    ��如何在SQL Server存储过程中获取另一存储过程的执行结果记录集?
    ��如何在存储过程中检索动态SQL语句的执行结果?
    ��如何实现类似SELECT * FROM (EXEC procedure_name @parameters_var) AS datasource ... 的功能?procedure_name是一个存储过程的名字,@parameters_var是过程参数列表
    ��如何将一个存储过程的执行结果记录集传递给另一个存储过程?
    ��存储过程中如何根据另一个存储过程的执行结果选择执行流程?
    ��存储过程中如何根据动态SQL语句的查询结果更改执行流程?
    ��一个存储过程A使用另一个存储过程B的名字(或一段SQL语句或一个不确定的表名,字段名)作为参数,如何在不改动存储过程B的情况下,对存储过程B的执行结果记录集进行过滤/更改,再将过滤/更改后的结果集返回给存储过程A的调用者?

    ��上面这些问题都有一个共同点,那就是都希望对存储过程(或动态SQL语句)的执行结果进行再处理,但是标准的SQL语句只能处理数据表,而一个存储过程(或动态SQL语句)的执行结果虽然是记录集,但它们本身不能当做数据表来处理。这样就大大限制了存储过程(或动态SQL语句)的应用范围,它们只能作为将记录集返回给应用程序前的最后一个处理层。如果我们可以像使用普通的数据表那样使用存储过程(或动态SQL语句)该有多好。
    ��这个问题我以前的解决方法是使用OPENQUERY()或OPENDATASOURCE(),但OPENQUERY()不仅要求建立一个链接服务器,而且执行性能也让人无法满意。OPENDATASOURCE()则要求提供连接字符串,这对系统后期的维护也是一个很大的麻烦。
    今天使用SQL Server联机丛书时无意中发现了一条SQL语句,竟然非常方便的解决了这个问题。这个语句就是INSERT语句。
    ��INSERT语句在帮助中的定义是这样的:
    INSERT [ INTO]
        { table_name WITH ( < table_hint_limited > [ ...n ] )
            | view_name
            | rowset_function_limited
        }
        {    [ ( column_list ) ]
            { VALUES
                ( { DEFAULT | NULL | expression } [ ,...n] )
                | derived_table
                | execute_statement
            }
        }
        | DEFAULT VALUES
    其中execute_statement的解释是"任何有效的 EXECUTE 语句,它使用 SELECT 或 READTEXT 语句返回数据。"。通常我们放在这个位置的就是一段SELECT语句。但帮助既然说"任何有效的 EXECUTE 语句",那么"EXEC procedure_name"也应该可以罗?想到这一点,马上决定动手验证一下。验证结果证实没问题。即下面这样的语句
     
    INSERT INTO table_name EXEC procedure_name @parameters_value
     
    确实可以正常工作。有了这个基础,我们也就有了解决本文开头那些问题的方法。
    ��基本思路是先创建一个临时表,通过INSERT ... EXEC ...语句将存储过程的返回结果保存到临时表中,接下来就可以像处理普通数据表那样对待这个临时表了。对于动态SQL语句,可以通过dbo.sp_executesql存储过程执行,或者直接作为EXEC的参数执行。具体的编写要求可以参考SQL Server联机丛书。这里只特别说明一下,临时表的表结构与存储过程(或动态SQL语句)返回的记录集的表结构兼容即可,不要求完全相同。如果直接通过EXEC执行动态SQL语句,SQL语句有4K的长度限制。

    最后给出两种最常见的处理流程:
    1。创建一个临时表#tmp,表结构与目标存储过程procedure_name的返回结果集兼容(兼容即可,不必相同)。
        CREATE TABLE #tmp(
            [columns_list]
        )
    2。执行存储过程并将存储过程的返回结果集插入临时表。
        INSERT INTO #tmp EXEC procedure_name @parameters_var
    3。现在可以使用(过滤,更改或检索)#tmp了。^_^
        IF EXISTS(SELECT * FROM #tmp)
        BEGIN
            --执行分支1
        END ELSE BEGIN
            --执行分支2
        END
        或者
        SELECT * FROM #tmp WHERE ...
    4。别忘了最后清除临时表。
        DROP TABLE #tmp
     
    对于动态SQL语句,只要将第二步改为
        INSERT INTO #tmp EXEC dbo.sp_executesql @querystring_value
    即可。
  • 相关阅读:
    Codechef EDGEST 树套树 树状数组 线段树 LCA 卡常
    BZOJ4319 cerc2008 Suffix reconstruction 字符串 SA
    Codechef STMINCUT S-T Mincut (CodeChef May Challenge 2018) kruskal
    Codeforces 316G3 Good Substrings 字符串 SAM
    Codechef CHSIGN Change the Signs(May Challenge 2018) 动态规划
    BZOJ1396 识别子串 字符串 SAM 线段树
    CodeForces 516C Drazil and Park 线段树
    CodeForces 516B Drazil and Tiles 其他
    CodeForces 516A Drazil and Factorial 动态规划
    SPOJ LCS2
  • 原文地址:https://www.cnblogs.com/shiyh/p/7171852.html
Copyright © 2011-2022 走看看