Compare procedure Definition within two databases - sql

We have an instance of Sql Server 2012,
In the Instance we have 2 dbs called A and B ( Assume A as production DB and B as Development DB and B is the exact copy of Database A )
suppose For Development Purpose,Some procedure ( Already Existed,Not Newly Created ) definition were changed in database B but not in A ( Production database ).
In order to Find the Procedures that are different by Definition i have came up with the following scenario,But the Problem is i not 100% Sure that this scenario works every time.
So please Suggest Your ideas On this.
Scenario
Temporary Table 1 ( A_PROCEDURE ) -- To Hold all the procedure name and Definition exists in database A ( Executed from Database A )
select * into A_PROCEDURE FROM (
Select routine_name,routine_definition from INFORMATION_SCHEMA.ROUTINES ) DTL;
Now From Database B i have Executed following Query To find All the Procedure Which are Not same by the Procedure Definition
SELECT T.ROUTINE_NAME B_PROC,
L.ROUTINE_NAME A_PROC,T.ROUTINE_DEFINITION B_PROC_DEF,L.ROUTINE_DEFINITION A_PROC_DEF
FROM INFORMATION_SCHEMA.ROUTINES T JOIN A.DBO.A_PROCEDURE L ON T.ROUTINE_NAME = L.ROUTINE_NAME
AND T.ROUTINE_DEFINITION <> L.ROUTINE_DEFINITION;
From the above Query i have found Procedures which are same by name But Not same by definition ( Which are Correct -manually Checked Line By line ).
So is this a proper way ? Should Consider anything else ? Please Share your ideas on this
Thanks and Best Regards,
Vishnudas

Hi Vishnudas: You need sp_HelpText system stored procedure. This utility stores the definition of every stored procedure in a SQL Server database engine.
It's worth for every DBA or developer to use a comparison tool. In the meanwhile, you can check this blog where you could write a script without stats about the in-line comparison of two stored procedures. There, you get an explanation about the use of sp_HelpText.
However, I suggest to use a comparison tool like SQL Compare tool, used by production teams in some middle and large companies. An useful top list is recommended and it was reviewed by another peers.

Related

How to query results from another query?

I am writing a Trans-SQL script against a MSSQL 2005 Server that intends to query file path of each database present. I am able to list out the database present in the system. But how do I run a separate query based on the results?
The following is the output from the list of databases using the command (SELECT name from sys.databases):
name
----
master
tempdb
model
msdb
Now i would like to take this database names (e.g. master, tempdb) and enter into another query namely (exec sp_helpdb <database_name>).
any ideas?
Not answering your question directly, but if you want to run a query for each db, you can use sp_msforeachdb.
sp_msforeachdb 'EXEC sp_helpdb [?]'
Otherwise, you're going to need to use the results to generate your SQL.
You can build a cursor based on that query then loop through the results, stuff them into a SQL variable, and use that variable to exec your sproc. Unfortunately I'm not able to give you a sample right now, but that is the way I would approach it.
In general, the answer to your question would be "use a subquery".
But in this case, you're using a SQL Server stored procedure. So the best approach is to write your own stored procedure to:
1) call sp_helpdb (or select from master..sysdatabases)
2) Iterate through the results
Here's an example:
http://www.mssqltips.com/sqlservertip/1070/simple-script-to-backup-all-sql-server-databases/
If i am understanding correct , you can use derived table here:-
select database.name (your query) from
(SELECT name from sys.databases) database

Finding stored procedures with errors in SQL Server 2008?

I have a database which consists of almost 200 tables and 3000 stored procedures.
I have deleted some fields from some tables, how can I now find stored procedures in which those deleted fields are referred?
Have a look at the FREE Red-Gate tool called SQL Search which does this - it searches your entire database for any kind of string(s).
It's a great must-have tool for any DBA or database developer - did I already mention it's absolutely FREE to use for any kind of use??
So in your case, you could type in the column name you deleted, and select to search only your stored procedures - and within a second or so, you'll have a list of all stored procs that contain that particular column name. Absolutely great stuff!
You can use sys.sql_modules
SELECT
OBJECT_NAME(object_id)
FROM
sys.sql_modules
WHERE
definitiion LIKE '%MyDeletedColumn%'
Or OBJECT_DEFINITION
The INFORMATION_SCHEMA views are unreliable for this because the definition is split over several nvarchar(4000) rows. The 2 methods above return nvarchar(max)
Edit: Given SQL Search is free as note by marc_s, this will a better solution.
select object_name(object_id), *
from sys.sql_module
where definition like '%ColName%'
One possible approach is to call each stored procedure with dummy parameters with SET SHOWPLAN_XML ON active. This won't run the procedure, but will generate an .xml representation of the plan - and will fail if referenced columns are missing. If you make use of #temp tables, however, this'll fail regardless. :(
You'd most likely want to automate this process, rather than writing out 3000 procedure calls.
DISCLAIMER: This isn't a bulletproof approach to picking up on missing columns, but good luck finding anything better!

Is it possible to create a temp table on a linked server?

I'm doing some fairly complex queries against a remote linked server, and it would be useful to be able to store some information in temp tables and then perform joins against it - all with the remote data. Creating the temp tables locally and joining against them over the wire is prohibitively slow.
Is it possible to force the temp table to be created on the remote server? Assume I don't have sufficient privileges to create my own real (permanent) tables.
This works from SQL 2005 SP3 linked to SQL 2005 SP3 in my environment. However if you inspect the tempdb you will find that the table is actually on the local instance and not the remote instance. I have seen this as a resolution on other forums and wanted to steer you away from this.
create table SecondServer.#doll
(
name varchar(128)
)
GO
insert SecondServer.#Doll
select name from sys.objects where type = 'u'
select * from SecondServer.#Doll
I am 2 years late to the party but you can accomplish this using sp_executeSQL and feeding it a dynamic query to create the table remotely.
Exec RemoteServer.RemoteDatabase.RemoteSchema.SP_ExecuteSQL N'Create Table here'
This will execute the temp table creation at the remote location..
It's not possible to directly create temporary tables on a linked remote server. In fact you can't use any DDL against a linked server.
For more info on the guidelines and limitations of using linked servers see:
Guidelines for Using Distributed Queries (SQL 2008 Books Online)
One work around (and off the top of my head, and this would only work if you had permissions on the remote server) you could:
on the remote server have a stored procedure that would create a persistent table, with a name based on an IN parameter
the remote stored procedure would run a query then insert the results into this table
You then query locally against that table perform any joins to any local tables required
Call another stored procedure on the remote server to drop the remote table when you're done
Not ideal, but a possible work around.
Yes you can but it only lasts for the duration of the connection.
You need to use the EXECUTE AT syntax;
EXECUTE('SELECT * INTO ##example FROM sys.objects; WAITFOR DELAY ''00:01:00''') AT [SERVER2]
On SERVER2 the following will work (for 1 minute);
SELECT * FROM ##example
but it will not work on the local server.
Incidently if you open a transaction on the second server that uses ##example the object remains until the transaction is closed. It also stops the creating statement on the first server from completing. i.e. on server2 run and the transaction on server1 will continue indefinately.
BEGIN TRAN
SELECT * FROM ##example WITH (TABLOCKX)
This is more accademic than of practical use!
If memory is not much of an issue, you could also use table variables as an alternative to temporary tables. This worked for me when running a stored procedure with need of temporary data storage against a Linked Server.
More info: eg this comparison of table variables and temporary tables, including drawbacks of using table variables.

SQL - How to insert results of Stored_Proc into a new table without specifying columns of new table?

Using SQL Server 2005, I'd like to run a stored procedure and insert all of the results into a new table.
I'd like the new table to have its columns automatically configured based upon the data returned by the stored procedure.
I am familiar with using the SELECT ... INTO syntax:
SELECT * INTO newtable FROM oldtable
Is this possible?
Edit for clarification: I'm hoping to accomplish something like:
Select * INTO newtable FROM exec My_SP
The only way to do this is w/ OPENROWSET against the local server:
SELECT * INTO #temp
FROM OPENROWSET (
'SQLOLEDB'
, 'Server=(local);TRUSTED_CONNECTION=YES;'
, 'SET FMTONLY OFF EXEC database.schema.procname'
) a
But this is kind of a last-ditch-gotta-do-it-damn-the-consequences kind of method. It requires elevated permissions, won't work for all procedures, and is generally inefficient.
More info and some alternatives here: http://www.sommarskog.se/share_data.html
This seems like a horrible design. You're really going to create a new table to store the results of a stored procedure, every time the stored procedure is called? And you really can't create the table in advance because you have absolutely no idea what kind of output the stored procedure has? What if the stored procedure returns multiple resultsets? What if it has side effects?
Okay, well, if that's what you really want to do...
One way to accomplish this is to use your local server as a linked server and utilize OPENQUERY. First you need to make sure your local server is configured for data access:
EXEC sp_serveroption 'local server name', 'DATA ACCESS', true;
Then you can do something like this:
SELECT * INTO dbo.newtable
FROM OPENQUERY('local server name', 'EXEC yourdb.dbo.yourproc;');
PS How are you going to write code that is going to perform SELECT INTO into a new table name every time (because you can only do SELECT INTO once)? Dynamic SQL? What happens if two users run this code at the same time? Does one of them win, and the other one just gets an error message?
A variation of the same is
create table somename
select * from wherever;

I traced a Stored Procedure as shown in the SQL Server 2005 Profiler. It's not found but works. Why?

This is pretty weird.
I have my Profiler open and it obviously shows that a stored procedure is called. I open the database and the SP list, but the SP doesn't exist. However, there's another SP whose name is the same except it has a prefix 'x'
Is SQL Server 2005 mapping the SP name to a different one for security purposes?
EDIT: I found out it's a Synonym, whatever that is.
In general, when you know an object exists because it's been used in a query, and you can't find it in the object tree in Management Studio, you can do this to find it.
select *
from sys.objects
where name = 'THE_NAME_YOU_WANT'
I just checked, and it works with Synonyms.
Possibly silly questions, but just in case... have you refreshed the SP list? Have you checked for a stored procedure of that name under a different owner? If you created the stored procedure without specifying the owner then it could be in the list under your ownership (or not at all if the list is filtered to only "dbo" for example).
You may not have permission to see all the objects in the database
Adding to the previous answers, it could also be under "System Stored Procedures", and if the name of the stored procedure begins with "sp_", it could also be in the master database.
The stored procedure will be inside the database you have selected at time of stored procedure creation. So search inside the database from which it is extracting data, otherwise it will be inside the master database. If still you are not able to find then first number solution is best one. i.e.
select * from sys.objects where name = 'name of stored procedure'