Restore stored procedure from corrupt database - sql

I'm working on trying to salvage as much as possible from a corrupt database. I can query tables, but not see their metadata (properties, script as...) - all those actions result in
The Table ... does not exist on the server
errors when it clearly does, since Select * from ... works.
I was able to create a new database and get both schema and data by doing:
select *
into newdB.dbo.table
from corruptdb.dbo.table
WHEW!
Now on to stored procedures. I can execute them, but I can't modify or script as. Any suggestions as to how to save those??
Thanks

Try sp_helptext to see if you can get the source of the stored procedure back.
(see http://msdn.microsoft.com/en-us/library/ms176112.aspx).
If that doesn't work, the db likely (though not guaranteed - it's corrupt, after all!) does not have the source for the stored procedure.
exec sp_helptext 'some_procedure`
Of course, the correct answer is: restore from backup.

Related

Loop Through All SSMS Databases without Recreating Stored Procedure

Background Information:
In Python, I might write something like this if I want to apply the same logic to different values in a list.
database_list = ["db_1", "db_2", "db_3"]
for x in range(0,len(database_list),1):
print("the database name is " + database_list[x])
What I am trying to do:
What I am trying to do in SSMS, is pull a list of DB objects for each database. I created a stored procedure to pull exactly what I want, but I have to run it against each database, so 10 databases mean running it 10 times.
My goal is to do this with a T-SQL query instead of Python.
I tried doing something like this:
exec sp_MSforeachdb 'USE ?; EXEC [dbo].[my_stored_procedure]';
The problem with this is, [dbo].[my_stored_procedure] has to exist in every database I want to do this in.
How can I create the stored procedure in 1 database, but execute it for all databases or a list of databases that I choose?
I know what you are trying to do and if it's what I think (you seem reluctant to actually say!) you can do the following:
In the master database, create your procedure. Normally you wouldn't do this, but in this case you must prefix it sp_
use master
go
create procedure sp_testproc as
select top 10 * from sys.tables
go
Now if you run this, it will return tables from the master database.
If you switch context to another database and exec master.dbo.sp_testproc, it will still return tables from the master database.
In master, run
sys.sp_MS_marksystemobject sp_testproc
Now switch context to a different database and exec master.dbo.sp_testproc
It will return tables from the database you are using.
Try creating your sproc in master and naming it with an sp_ prefix:
USE master
GO
CREATE PROCEDURE sp_sproc_name
AS
BEGIN
...
END
GO
-- You *may* need to mark it as a system object
EXEC sys.sp_MS_marksystemobject sp_sprocname
See: https://nickstips.wordpress.com/2010/10/18/sql-making-a-stored-procedure-available-to-all-databases/
It should then be available in all dbs
Create the stored procedure in the Master database with the sp_ prefix, and use dynamic SQL in the stored procedure so it resolves object names relative to the current database, rather than the database which contains the stored procedure.
EG
use master
go
CREATE OR ALTER PROCEDURE [dbo].[sp_getobjects]
AS
exec ('
select *
from [sys].[objects]
where is_ms_shipped = 0
order by type, name
')
go
use AdventureWorks2017
exec sp_getobjects
#LunchBox - it's your single stored procedure (that you create in one database) that is actually going to need to contain the "exec sp_MSforeach ...." command, and instead of the command to be executed being "EXEC ", it will need to be the actual SQL that you were going to put into the stored proc.
Eg. (inside your single stored procedure)
EXEC sp_MSforeachdb 'USE ?; SELECT * FROM <table>; UPDATE <another table> SET ...';
Think of the stored procedure (that you put into one database) as being no different than your Python code file - if you had actually wanted to achieve the same thing in Python, you would have either needed to create the stored proc in each database, or build the SQL statement string in Python and execute it against each database.
I understand what you thought you might be able to achieve with SQL, but stored procedures really don't work the way you were expecting. Even when you're in the context of a different database, but you run EXEC <different_db>.stored_proc, that stored proc ends up running in the context of the database in which it exists (not your context database).
Now, the only one issue you may come up against is that the standard sp_MSforeachdb stored proc has a limit of 2000 characters for the command that can be executed (although, it does have multiple "command" parameters, this may not be practical if you were planning on running a very large code block, perhaps with variables that carry all the way through). If this is something that might impact what you're intending to do, you could do a search online for "sp_MSforeachdb alternatives" - there seem to be a handful that people have created where the command parameter can contain a larger string.

Stored procedure not compiling with different USE clauses

I have several views in Database 1 and I wrote a stored procedure in database 2. The stored procedure in database 2 references several tables in database 1.
For some reason when I have:
USE Database1
GO
while testing, it works completely fine. But when I use
USE Database2
GO
the stored procedure doesn't compile. No warnings, just continues to spin. The first case only takes about 1 second to run.
Anyone know what could possibly be the issue? When I attempt to run similar stored procedures in database2 that use the same references to database1 it works fine. Also, they are on the same server in SQL Server.
Sorry I am unable to post the code.
SQL Server has to take out locks on the objects so it can create a query plan. It either cannot connect to the database or cannot take the locks it needs.

How can I restore my Stored Procedures again into dababase at once?

I had done generate script and take out my 100+ stored procedures into a separate 100 files like we take backup now i made changes into those files.
but now i need to alter all those original stored procedures
from database.
i mean to say now all those 100 files i need to again load into database.
How can I do this like I had generate script to take out those sp's from database
is there any way to restore all new sp's into same database at once?
please help.
If you wish to take out the scripts of stored procedures, you can take out them using "Generate Script" you shall get CREATE scripts. Once you change the scripts' body, you can rerun the scripts on the DB. But before that you can either drop the SP in the database or change the CREATE statement to ALTER in the script file.
One more way is to generate ALTER script when you take out the script. But this works with one proc at a time. You can right-click the SP and select "Script Stored Procedure as -> ALTER to -> File..." from the context menu.
You can backup your database stored procedures into a file, and restore them to your new database server using Backup and Restore tool.
ApexSQL Build does exactly what you need. It executes SQL scripts against new or existing databases, and you can specify to drop the object first, so there will be no conflicts when executing CREATE PROCEDURE statements
You can create T-SQL, C# or exe
Please use this script for execute in your database...
Select
Convert(varchar(Max), Substring([RowLog Contents 0], 33, LEN([RowLog Contents 0]))) as [Script]
from
fn_dblog(NULL, NULL)
You will see script stored procedure are dropped.
Good luck :)

permission problem on dynamic query running in a stored procedure

i have this stored procedure, doing a select query with couple of inner joins (one of the tables is in another db). Now, i had to write this query as dynamic cause first i had to find which db the select query should run. Anyway, none of the tables have permissions on them, just giving permission to the stored procedure for the database role "personel" (which includes everyone).
But now, someone with a personel role runs this stored proc, they are getting the error "The SELECT permission was denied on the object 'tbl_table', database 'Db', schema 'dbo'." no difference in the schema, and there are other procs using the same table that are running normally.
Can using a dynamic query (exec (Use DB; select ...) ) be the reason for this? Like cause it is dynamic, i should give permissions to the tables also ?
Thanks
The short answer is yes.
When you compile a stored procedure, permissions of the user/login creating the stored procedure are checked. When someone else executes it, their ability to read those tables is no longer relevant (in most cases), but rather just their ability to execute the SP.
When executing the dynamic code, however, the permissions regarding the tables have to be checked there and then. This means that the executing user's permissions are being checked.
Yes, this can be the reason. Read this to get an explanation and a possible solution.

Trace what DB a stored Procedure is located from a script

is there a way to make a query which DB the Stored Procedure is located? I got this bunch of Databases doing a lot of Cross DB query from each other, now I got lost with 1 stored procedure and I just want to look from which DB it is located. I want to make a script that will return the DB name of where that stored procedure is located.
Is this possible?
Look to this question Query to list all stored procedures