Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function 如何使用PL/SQL函数比较两个表?_Function_Plsql - Fatal编程技术网

Function 如何使用PL/SQL函数比较两个表?

Function 如何使用PL/SQL函数比较两个表?,function,plsql,Function,Plsql,我是plsql新手,正在努力编写代码。。我想使用plsql函数比较两个表(除了记录外,两个表完全相同)。输入参数将是(表1,表2)-它应该比较表1和表2并返回三个输出 表之间的任何不匹配记录 表1中存在但表2中不存在的任何行 表2中存在但表1中不存在的任何行 我用SQL编写了这个查询,它工作了,但我在这里硬编码了一个特定的表名。 请告知如何转换为函数 SET TERMOUT OFF CONCAT OFF VERIFY OFF SET FEEDBACK OFF SET MARKUP HTML ON

我是plsql新手,正在努力编写代码。。我想使用plsql函数比较两个表(除了记录外,两个表完全相同)。输入参数将是(表1,表2)-它应该比较表1和表2并返回三个输出

  • 表之间的任何不匹配记录
  • 表1中存在但表2中不存在的任何行
  • 表2中存在但表1中不存在的任何行 我用SQL编写了这个查询,它工作了,但我在这里硬编码了一个特定的表名。 请告知如何转换为函数

    SET TERMOUT OFF CONCAT OFF VERIFY OFF
    SET FEEDBACK OFF
    SET MARKUP HTML ON SPOOL ON
    SPOOL ACTION.HTML
    set pages 1000 lines 125
    
    ----
    PROMPT SHOWING THE DIFFERENCE WITH THE MATCHING RECORDS FOR TABLE ACTION
    BREAK ON ACTIONID  duplicates skip page
    column tblname format a10
    select ACTIONID,tblname "tblname",ACTIONDESC,ACTIONNAME
    from ((SELECT 'OLD VALUES' tblname,ACTIONID,ACTIONDESC,ACTIONNAME
    FROM 'DEPL_ACTION
    MINUS
    SELECT 'NEW VALUES'  tblname,ACTIONID,ACTIONDESC,ACTIONNAME
    FROM ACTION )
    UNION ALL
    ( SELECT 'NEW VALUES'  tblname,ACTIONID,ACTIONDESC,ACTIONNAME
    FROM ACTION
    MINUS
    SELECT 'OLD VALUES' tblname,ACTIONID,ACTIONDESC,ACTIONNAME
    FROM 'DEPL_ACTION )) aa  where (ACTIONID) in ( select ACTIONID from (
    (SELECT ACTIONID,ACTIONDESC,ACTIONNAME
    FROM 'DEPL_ACTION
    MINUS
    SELECT ACTIONID,ACTIONDESC,ACTIONNAME
    FROM ACTION )
    UNION ALL
    ( SELECT ACTIONID,ACTIONDESC,ACTIONNAME
    FROM ACTION
    MINUS
    SELECT ACTIONID,ACTIONDESC,ACTIONNAME
    FROM 'DEPL_ACTION ) )  group by ACTIONID having count(*) > 1 ) order by ACTIONID;
    CLEAR BREAKS
    
    PROMPT SHOWING THE EXTRA RECORDS IN OLD VALUES FOR TABLE ACTION
    select ACTIONID,tblname "tblname",ACTIONDESC,ACTIONNAME
    from ((SELECT 'OLD VALUES' tblname,ACTIONID,ACTIONDESC,ACTIONNAME
    FROM 'DEPL_ACTION
    MINUS
    SELECT 'NEW VALUES'  tblname,ACTIONID,ACTIONDESC,ACTIONNAME
    FROM ACTION )
    UNION ALL
    ( SELECT 'NEW VALUES'  tblname,ACTIONID,ACTIONDESC,ACTIONNAME
    FROM ACTION
    MINUS
    SELECT 'OLD VALUES' tblname,ACTIONID,ACTIONDESC,ACTIONNAME
    FROM 'DEPL_ACTION )) aa  where (ACTIONID) in ( select ACTIONID from (
    (SELECT ACTIONID,ACTIONDESC,ACTIONNAME
    FROM 'DEPL_ACTION
    MINUS
    SELECT ACTIONID,ACTIONDESC,ACTIONNAME
    FROM ACTION )
    UNION ALL
    ( SELECT ACTIONID,ACTIONDESC,ACTIONNAME
    FROM ACTION
    MINUS
    SELECT ACTIONID,ACTIONDESC,ACTIONNAME
    FROM 'DEPL_ACTION ) )  group by ACTIONID having count(*) = 1 )  order by ACTIONID;
    
    PROMPT SHOWING THE EXTRA RECORDS IN NEW VALUES FOR TABLE ACTION
    select ACTIONID,tblname "tblname",ACTIONDESC,ACTIONNAME
    from ((SELECT 'OLD VALUES' tblname,ACTIONID,ACTIONDESC,ACTIONNAME
    FROM 'DEPL_ACTION
    MINUS
    SELECT 'NEW VALUES'  tblname,ACTIONID,ACTIONDESC,ACTIONNAME
    FROM ACTION )
    UNION ALL
    ( SELECT 'NEW VALUES'  tblname,ACTIONID,ACTIONDESC,ACTIONNAME
    FROM ACTION
    MINUS
    SELECT 'OLD VALUES' tblname,ACTIONID,ACTIONDESC,ACTIONNAME
    FROM 'DEPL_ACTION )) aa  where (ACTIONID) in ( select ACTIONID from (
    (SELECT ACTIONID,ACTIONDESC,ACTIONNAME
    FROM 'DEPL_ACTION
    MINUS
    SELECT ACTIONID,ACTIONDESC,ACTIONNAME
    FROM ACTION )
    UNION ALL
    ( SELECT ACTIONID,ACTIONDESC,ACTIONNAME
    FROM ACTION
    MINUS
    SELECT ACTIONID,ACTIONDESC,ACTIONNAME
    FROM 'DEPL_ACTION ) )  group by ACTIONID having count(*) = 1 ) order by ACTIONID;
    
    
    
    SET MARKUP HTML OFF
    SPOOL OFF
    EXIT
    

    我不会为它创建一个最终功能,维护它将非常困难。每个表对创建一个包

    标题:

    CREATE OR REPLACE PACKAGE tab_a_pkg AS
    
        TYPE tab_a_ntt IS TABLE OF tab_a%ROWTYPE;
    
        FUNCTION mismatched RETURN tab_a_ntt;
    
        FUNCTION a_minus_b RETURN tab_a_ntt;
    
        FUNCTION b_minus_a RETURN tab_a_ntt;
    
    END tab_a_pkg;
    
    正文:

    运行:


    这个proc存储可能是在您搜索时创建的 我把它发布到这个站点的另一个主题中,但我不记得是哪一个:)

    用于比较具有相同主键的两个表中的选定字段 ps_TableGap'tbl1','tbl2','fld1,fld2,fld3…tbl1的字段','Fld4,fld5,fld6…tbl2的字段(可选us,因为tbl1为空)'

    根据tbl1“删除”、“添加”、“差距”,您有3个结果 tbl2的字段前缀为u,表示不同(需要有不同的字段名称才能在报告服务中推送结果)


    你在挣扎哪一部分?在函数中接受表名,或者从函数中投影行,或者其他什么?如果我想执行上述操作,我应该使用哪种返回类型???@davidridge首先,我想问为什么要对函数执行此操作--结果直接来自SQL,因此为了方便起见,可以将逻辑嵌入到视图中,但是使用函数似乎不是一个好选择,我必须将它嵌入到套件中。所以我不能使用sqlplus。因此,我们将以加密的方式获得DB连接,因此我们考虑使用函数@davidridgeCan此环境不只是对数据库运行查询吗?上述代码工作正常,如果我们为每对表创建包,我必须比较12对表,这是否意味着12个不同的包@斯尔基夫妇,没错。如果你必须为其中一对夫妇做一个改变,其他11对是安全的。它易于维护、测试和发布。
    CREATE OR REPLACE PACKAGE BODY tab_a_pkg AS
    
        FUNCTION mismatched RETURN tab_a_ntt
        AS
            l_return  tab_a_ntt;
        BEGIN
            SELECT  NVL(col_a1, col_b1) AS col_1
            ,       NVL(col_a2, col_b2) AS col_2
            BULK    COLLECT INTO l_return
            FROM    tab_a
            FULL    JOIN tab_b
            ON      col_a1 = col_b1
            AND     col_a2 = col_b2
            WHERE   col_a1 IS NULL
            OR      col_b1 IS NULL;
    
            RETURN l_return;
        END mismatched;
    
    
    
        FUNCTION a_minus_b RETURN tab_a_ntt
        AS
            l_return  tab_a_ntt;
        BEGIN
            SELECT  *
            BULK    COLLECT INTO l_return
            FROM
            (
                SELECT * FROM tab_a
                MINUS
                SELECT * FROM tab_b
            );
    
            RETURN l_return;
        END a_minus_b;
    
    
    
        FUNCTION b_minus_a RETURN tab_a_ntt
        AS
            l_return  tab_a_ntt;
        BEGIN
            SELECT  *
            BULK    COLLECT INTO l_return
            FROM
            (
                SELECT * FROM tab_b
                MINUS
                SELECT * FROM tab_a
            );
    
            RETURN l_return;
        END b_minus_a;
    
    END tab_a_pkg;
    
    DECLARE
        l_tab_a  tab_a_pkg.tab_a_ntt;
    BEGIN
        l_tab_a := tab_a_pkg.mismatched();
    
        FOR indx IN 1..l_tab_a.COUNT LOOP
            DBMS_OUTPUT.PUT_LINE(l_tab_a(indx).col_a1 || ' ' || l_tab_a(indx).col_a2);
        END LOOP;
        DBMS_OUTPUT.PUT_LINE('------');
    
    
        l_tab_a := tab_a_pkg.a_minus_b();
    
        FOR indx IN 1..l_tab_a.COUNT LOOP
            DBMS_OUTPUT.PUT_LINE(l_tab_a(indx).col_a1 || ' ' || l_tab_a(indx).col_a2);
        END LOOP;
        DBMS_OUTPUT.PUT_LINE('------');
    
    
        l_tab_a := tab_a_pkg.b_minus_a();
    
        FOR indx IN 1..l_tab_a.COUNT LOOP
            DBMS_OUTPUT.PUT_LINE(l_tab_a(indx).col_a1 || ' ' || l_tab_a(indx).col_a2);
        END LOOP;
        DBMS_OUTPUT.PUT_LINE('------');
    END;
    /*
    23 223
    24 224
    13 123
    14 124
    ------
    13 123
    14 124
    ------
    23 223
    24 224
    ------
    */
    
    /****** Object:  StoredProcedure [dbo].[ps_TableGap]    Script Date: 10/03/2013 16:03:44 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    
    -- =============================================
    -- Author:       Arnaud ALLAVENA
    -- Create date: 03.10.2013
    -- Description: Compare tables
    -- =============================================
    alter PROCEDURE [dbo].[ps_TableGap]
        -- Add the parameters for the stored procedure here
        @Tbl1 as varchar(100),@Tbl2 as varchar(100),@Fld1 as varchar(1000), @Fld2 as varchar(1000)= ''
    AS
    BEGIN
        -- SET NOCOUNT ON added to prevent extra result sets from
        -- interfering with SELECT statements.
    
        SET NOCOUNT ON;
    --Variables
    --@Tbl1 = table 1
    --@Tbl2 = table 2
    --@Fld1 = Fields to compare from table 1
    --@Fld2 Fields to compare from table 2
    Declare @SQL varchar(8000)= '' --SQL statements
    Declare @nLoop int = 1 --loop counter
    Declare @Pk varchar(1000)= '' --primary key(s) 
    Declare @Pk1 varchar(1000)= '' --first field of primary key
    declare @strTmp varchar(50) = '' --returns value in Pk determination
    declare @FldTmp varchar (1000) = '' --temporarily fields for alias calculation
    
    --If @Fld2 empty we take @Fld1
    --fields rules: fields to be compare must be in same order and type - always returns Gap
    If @Fld2 = '' Set @Fld2 = @Fld1
    
    --Change @Fld2 with Alias prefix xxx become _xxx 
    while charindex(',',@Fld2)>0
    begin
        Set @FldTmp = @FldTmp + (select substring(@Fld2,1,charindex(',',@Fld2)-1) + ' as _' + substring(@Fld2,1,charindex(',',@Fld2)-1) + ',')
        Set @Fld2 = (select ltrim(right(@Fld2,len(@Fld2)-charindex(',',@Fld2))))
    end
    Set @FldTmp = @FldTmp + @Fld2 + ' as _' + @Fld2
    Set @Fld2 = @FldTmp
    
    --Determinate primary key jointure
    --rule: same pk in both tables
    Set @nLoop = 1
    Set @SQL = 'Declare crsr cursor for select COLUMN_NAME from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where TABLE_NAME = '''
     + @Tbl1 + ''' or TABLE_SCHEMA + ''.'' + TABLE_NAME = ''' + @Tbl1 +  ''' or TABLE_CATALOG + ''.'' + TABLE_SCHEMA + ''.'' + TABLE_NAME = ''' + @Tbl1 
     + ''' order by ORDINAL_POSITION'
    exec(@SQL)
    open crsr 
    fetch next from crsr into @strTmp
    while @@fetch_status = 0
    begin 
        if @nLoop = 1 
        begin 
            Set @Pk = 's.' + @strTmp + ' = b._' + @strTmp
            Set @Pk1 = @strTmp
            set @nLoop = @nLoop + 1 
        end 
        Else
        Set @Pk = @Pk + ' and s.' + @strTmp + ' = b._' + @strTmp
    fetch next from crsr into @strTmp 
    
    end 
    close crsr
    deallocate crsr
    
    --SQL statement build
    set @SQL = 'select case when s.' + @Pk1 + ' is null then ''Del'' when b._' + @Pk1 + ' is null then ''Add'' else ''Gap'' end as TypErr, '''
    set @SQL = @SQL + @Tbl1 +''' as Tbl1, s.*, ''' + @Tbl2 +''' as Tbl2 ,b.* from (Select ' + @Fld1 + ' from ' + @Tbl1
    set @SQL = @SQL + ' EXCEPT SELECT ' + @Fld2 + ' from ' + @Tbl2 + ')s full join (Select ' + @Fld2 + ' from ' + @Tbl2 
    set @SQL = @SQL + ' EXCEPT SELECT ' + @Fld1 + ' from ' + @Tbl1 +')b on '+ @Pk 
    
    --Run SQL statement
    Exec(@SQL)
    END