sp_RefreshSQLModule run on a view completely changed the view definition

  • SQL Version:
    Microsoft SQL Server 2008 R2 (SP3) - 10.50.6000.34 (X64)
        Aug 19 2014 12:21:34
        Copyright (c) Microsoft Corporation
        Standard Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) (Hypervisor)

    Used sp_RefreshSQLModule to identify objects that would not compile. 
    In 2 cases for views this command completely changed the view definition. it was like there is some cached view definition that this command used to re-write the view. It added commented out lines that were not in the view previously and dropped a column from the select.

    From what i read it's primarily used to update meta-data in case an underlying object changed. 
    Can anyone shed some light on why this happened and what this command ACTUALLY does?

  • Tom Van Harpen - Friday, October 5, 2018 11:07 AM

    SQL Version:
    Microsoft SQL Server 2008 R2 (SP3) - 10.50.6000.34 (X64)
        Aug 19 2014 12:21:34
        Copyright (c) Microsoft Corporation
        Standard Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) (Hypervisor)

    Used sp_RefreshSQLModule to identify objects that would not compile. 
    In 2 cases for views this command completely changed the view definition. it was like there is some cached view definition that this command used to re-write the view. It added commented out lines that were not in the view previously and dropped a column from the select.

    From what i read it's primarily used to update meta-data in case an underlying object changed. 
    Can anyone shed some light on why this happened and what this command ACTUALLY does?

    Changes to the underlying structures of views, stored procedures etc can change and may not be reflected in the dependent objects. You can create a view for a table with two columns that does something like Select * from tableA. Select from that view and it pulls the table data. Add a column to that table and that column will not show up in the view until the view is refreshed. Before the refresh, you will see just the original two columns.
    So the meta data needs to be updated as you already read. In terms of the specifics of what it does exactly....sp_refreshsqlmodule (or sp_refreshview) call an undocumented stored procedure named sys.sp_refreshsqlmodule_internal
    The code for sp_refreshsqlmodule_internal that does the actual refresh is:
    -- REFRESH MODULE DEFINITION
    EXEC %%Module(ID = @objid).Refresh(NameSpaceClass = @ns)

    So what is actually happening when it's executed is internal to Microsoft.

    Sue

  • Thanks Sue,
    I understand the part about select * in a view (which we never use) and how changing a table won't be reflected in the view. 
    But what happened here is the command replaced the view definition with a completely different one. It used an old version of the view that we had not used in a long time.

    I'm going to restore the db and run Object_definition and see if it gives me something different that what the view currently is.

    I will say after doing an Alter View then the refresh command ran ok without changing the view.

    I guess what this comes down to is whatever SQL had for the view def didn't match what the view really was. It seems the refresh command just rebuilds the view based on the saved definition.

  • Tom Van Harpen - Friday, October 5, 2018 12:31 PM

    Thanks Sue,
    I understand the part about select * in a view (which we never use) and how changing a table won't be reflected in the view. 
    But what happened here is the command replaced the view definition with a completely different one. It used an old version of the view that we had not used in a long time.

    I'm going to restore the db and run Object_definition and see if it gives me something different that what the view currently is.

    I will say after doing an Alter View then the refresh command ran ok without changing the view.

    I guess what this comes down to is whatever SQL had for the view def didn't match what the view really was. It seems the refresh command just rebuilds the view based on the saved definition.

    That would be a pretty huge bug if it's refreshed with the incorrect definition.
    Any chance someone else could have been trying to address issues with the view?

    Sue

  • Fwiw, I usually stick to sp_refreshview for views, and only use the broader module proc when I need to.

    SQL DBA,SQL Server MVP(07, 08, 09) A socialist is someone who will give you the shirt off *someone else's* back.

  • There's only a few of us here. These views have been in use for some time. 
    So now i'm pretty sure that renaming views in SSMS is the culprit. 

    I have a view named GetSalesData and a view named GetSalesData_WORegionID

    What probably happened is one existed it was modified using a create statement and given the new name and the other view was simply renamed. 

    When i execute this:
    SELECT OBJECT_DEFINITION(OBJECT_ID('[fact].[GetSalesData_WORegionID]'))

    I get this result

    CREATE view [fact].[GetSalesData] AS SELECT ....

    When i did the RefreshSQLModule it used the definition from before the rename, thereby reverting the view to an old version.

  • ScottPletcher - Friday, October 5, 2018 2:32 PM

    Fwiw, I usually stick to sp_refreshview for views, and only use the broader module proc when I need to.

    Yeah i haven't tried that, from what i read in BOL they function identically for views. RefreshSQLModule just has the added Class parm in case you are doing server or db triggers.
    I get the same result with both.

  • Tom Van Harpen - Friday, October 5, 2018 2:54 PM

    There's only a few of us here. These views have been in use for some time. 
    So now i'm pretty sure that renaming views in SSMS is the culprit. 

    I have a view named GetSalesData and a view named GetSalesData_WORegionID

    What probably happened is one existed it was modified using a create statement and given the new name and the other view was simply renamed. 

    When i execute this:
    SELECT OBJECT_DEFINITION(OBJECT_ID('[fact].[GetSalesData_WORegionID]'))

    I get this result

    CREATE view [fact].[GetSalesData] AS SELECT ....

    When i did the RefreshSQLModule it used the definition from before the rename, thereby reverting the view to an old version.

    When you change the name in SSMS, it executes sp_rename. And sp_rename comes with a set of it's own issues explained in the documentation:
    sp_rename (Transact-SQL)
    Renaming a stored procedure, function, view, or trigger will not change the name of the corresponding object either in the definition column of the sys.sql_modules catalog view or obtained using the OBJECT_DEFINITION built-in function. Therefore, we recommend that sp_rename not be used to rename these object types. Instead, drop and re-create the object with its new name.

    So you were heading down the right path on that one - it's the rename that caused the issues.

    Sue

  • Sue_H - Friday, October 5, 2018 3:39 PM

    Tom Van Harpen - Friday, October 5, 2018 2:54 PM

    There's only a few of us here. These views have been in use for some time. 
    So now i'm pretty sure that renaming views in SSMS is the culprit. 

    I have a view named GetSalesData and a view named GetSalesData_WORegionID

    What probably happened is one existed it was modified using a create statement and given the new name and the other view was simply renamed. 

    When i execute this:
    SELECT OBJECT_DEFINITION(OBJECT_ID('[fact].[GetSalesData_WORegionID]'))

    I get this result

    CREATE view [fact].[GetSalesData] AS SELECT ....

    When i did the RefreshSQLModule it used the definition from before the rename, thereby reverting the view to an old version.

    When you change the name in SSMS, it executes sp_rename. And sp_rename comes with a set of it's own issues explained in the documentation:
    sp_rename (Transact-SQL)
    Renaming a stored procedure, function, view, or trigger will not change the name of the corresponding object either in the definition column of the sys.sql_modules catalog view or obtained using the OBJECT_DEFINITION built-in function. Therefore, we recommend that sp_rename not be used to rename these object types. Instead, drop and re-create the object with its new name.

    So you were heading down the right path on that one - it's the rename that caused the issues.

    Sue

    Well yep that explains it! 
    Learned something new, actually 2 things. The first is don't rename stuff, and the second is that SQL keeps 2 definitions of objects. One you get when you do a Script as Create/Alter and the other from sys.sql_modules/Object_definition.
    Thanks for your help Sue!

  • I don't use sp_rename so I've not run into this but, good lord!!!  What a land mine MS put into their code.  Oh sure, it's "documented"...

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • EDIT: What actually happened is running refresh on a view changed a different view, different from what the post title says.

    Created a script to find mismatching entries between sys.all_objects and sys.sql_module. 
    I adapted that to make it a little demo script... 


    -- drop the test views
    IF EXISTS ( SELECT 1 FROM sys.all_objects WHERE object_id = OBJECT_ID('dbo.TestView1') )
    DROP VIEW dbo.TestView1;
    GO
    IF EXISTS ( SELECT 1 FROM sys.all_objects WHERE object_id = OBJECT_ID('dbo.TestView2') )
    DROP VIEW dbo.TestView2;
    GO

    IF EXISTS ( SELECT 1 FROM sys.all_objects WHERE object_id = OBJECT_ID('dbo.TestView1_Rename') )
    DROP VIEW dbo.TestView1_Rename;
    GO

    -- create the test views
    CREATE VIEW dbo.TestView1
    AS
    (SELECT
      1 AS mycol);
    GO

    CREATE VIEW dbo.TestView2
    AS
    (SELECT
      9999 AS MyColumnName);
    GO

    -- rename testview1 to TestView1_Rename
    EXEC sys.sp_rename
    @objname = N'dbo.TestView1'
    ,@newname = N'TestView1_Rename'
    ,@objtype = 'OBJECT';
    GO
    -- rename testview2 to testview1
    EXEC sys.sp_rename
    @objname = N'dbo.TestView2'
    ,@newname = N'TestView1'
    ,@objtype = 'OBJECT';
    GO

    -- find object definitions that dont have the object name within the definition according to all object names.
    -- Now this is not the best approach since any occurrence of that name within the def will exclude the result.
    -- but its a start.
    SELECT
    ao.name AS AllObjectsName
    ,ao.object_id AS AllObjectsID
    ,asm.definition AS SQLModuleDefinition
    ,asm.object_id AS SQLModuleID
    FROM
    sys.all_sql_modules asm
    JOIN
    sys.all_objects ao
    ON ao.object_id = asm.object_id
    WHERE
    asm.definition NOT LIKE '%' + ao.name + '%';

    -- SSMS now shows TestView1 and TestView1_Rename
    -- TestView1 shows the definition of TestView2 (as it should since it was renamed from that)

    -- Script TestView1 as create to new query window give this:

    /*
         CREATE VIEW [dbo].[TestView1]
            AS
            (SELECT
          9999 AS MyColumnName);
    */

    -- Try to run the refresh command on TestView1
    /*
    EXEC sys.sp_refreshsqlmodule
    @name = N'dbo.TestView1'
    */
    -- Result: Msg 208, Level 16, State 6, Procedure sp_refreshsqlmodule_internal, Line 75 [Batch Start Line 66]
    --Invalid object name 'dbo.TestView2'.

    -- now run the refresh command on the renamed TestView1
    /*
    EXEC sys.sp_refreshsqlmodule
    @name = N'dbo.TestView1_Rename'
    */

    -- now check testview1.... The refresh of TestView1_Rename actually changed TestView1 to a something completely different.
    -- Script as Create to new query window:
    /*
    CREATE VIEW [dbo].[TestView1]
    AS
    (SELECT
      1 AS mycol);
    */

  • + 1 informative!

    Thanks for the heads up!

Viewing 12 posts - 1 through 11 (of 11 total)

You must be logged in to reply to this topic. Login to reply