How to Stop SSMS 2012 from scripting SPs using sp_executesql

三世轮回 提交于 2019-12-05 12:25:54

问题


I realise this is a very similar question to Stop SSMS from scripting SPs using sp_executesql?

However, they seem to have changed the behaviour with SSMS 2012.

If you have the 'Check for existence' option selected, as in:

... it now generates an IF NOT EXISTS for the proc about to be created, as well as an IF EXISTS for the previous drop proc, if, as I usually do, I select the DROP and CREATE option:

This forces it to script the CREATE using sp_executesql. It's pointless, since you don't need the IF NOT EXISTS check on the CREATE, if the DROP has just dropped it.

It doesn't seem possible to have the one without the other.

Any ideas?


回答1:


You can't do this without the dynamic SQL because a stored procedure has to be in its own batch. Therefore you can't say:

IF <some condition>
  <start a new batch>

The only way to keep that in the same batch is to use sp_executesql.

If you're going to script the DROP and CREATE simultaneously, just do it without the check for object existence. This will give you:

DROP PROCEDURE ...;
GO
CREATE PROCEDURE ...;
GO

Who cares if the DROP fails? (It shouldn't, because you just scripted from it!)

If you're scripting this for another system that might have the object, you'll get an error message for the DROP when it doesn't, but the CREATE will still happen, so you can ignore the DROP errors. If you really want you can manually wrap the DROP statements in TRY/CATCH but I don't think it's necessary.

If you need to do this for a lot of procedures, or if you really need the process to not generate benign errors, I suggest you abandon Management Studio's primitive scripting options and use a 3rd party tool for this. They'll have already dealt with many of the issues you haven't yet come across, but will. I blogged about this:

http://bertrandaaron.wordpress.com/2012/04/20/re-blog-the-cost-of-reinventing-the-wheel/




回答2:


The closest you can get to this functionality is to go under tools, options, SQL Server Object Explorer, Scripting, then set the Check for Object Existing to false.

The drawback is that if you do this then drops and creates will always try to drop even if the object does not exist. The ideal solution would be a setting that allowed your script to look like the example below for creating Views, Procedures, and User-Defined Functions.

/****** Object:  View [dbo].[vEmployees]    Script Date: 9/14/2012 9:18:57 AM ******/
IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vEmployees]'))
DROP VIEW [dbo].[vEmployees]
GO

CREATE VIEW [dbo].[vEmployees]
AS
    SELECT DISTINCT
        Employees.EmployeeID,
        FirstName,
        LastName
    from
        Employees
            JOIN Sales on Employees.EmployeeID=Sales.EmployeeID
GO

In short if the scripting engine thinks of the drop and create together in checking for object existance it does not need to put the condition on the create.




回答3:


I found a good solution to this problem. You must make "two passes" when scripting. During the first pass, select the options to Check for Existence AND for only the DROP script. Then, on the second pass, de-select the option for Check for Existence and select the CREATE script. In addition, use the option Append To File. Then when running the generate scripts on the second pass, uncheck the option for "Overwrite File". This will only work if you are generating a separate file for each object.




回答4:


I also struggled with the same issue. If you need to script out the objects for an entire database, you might want to consider ApexSQL Script. I tried several tools and ApexSQL scripted the objects exactly how I needed. (if object exists, then drop. create the object). I believe it also works from the command-line. Note, it is shareware; I've only used the evaluation version because I only needed it a handful of times.

Below is an example of the output for a procedure after some configuration.

IF (EXISTS(SELECT * FROM sys.objects WHERE [object_id] = OBJECT_ID(N'[dbo].[myProcedure]') AND [type]='P'))
DROP PROCEDURE [dbo].[myProcedure]
GO

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE dbo.myProcedure
AS
    select 1 as a
GO


来源:https://stackoverflow.com/questions/10620984/how-to-stop-ssms-2012-from-scripting-sps-using-sp-executesql

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!