Is there a way to drop all objects in a db, with the objects belonging to two different schemas?
I had been previously working with one schema, so I query all objects using:
Select * From sysobjects Where type=...
then dropped everything I using
Drop Table ...
Now that I have introduced another schema, every time I try to drop it says something about I don't have permission or the object does not exist. BUT, if I prefix the object with the [schema.object] it works. I don't know how to automate this, cause I don't know what objects, or which of the two schemas the object will belong to. Anyone know how to drop all objects inside a db, regardless of which schema it belongs to?
(The user used is owner of both schemas, the objects in the DB were created by said user, as well as the user who is removing the objects - which works if the prefix I used IE. Drop Table Schema1.blah)
Use sys.objects in combination with OBJECT_SCHEMA_NAME to build your DROP TABLE statements, review, then copy/paste to execute:
SELECT 'DROP TABLE ' +
QUOTENAME(OBJECT_SCHEMA_NAME(object_id)) + '.' +
QUOTENAME(name) + ';'
FROM sys.objects
WHERE type_desc = 'USER_TABLE';
Or use sys.tables to avoid need of the type_desc filter:
SELECT 'DROP TABLE ' +
QUOTENAME(OBJECT_SCHEMA_NAME(object_id)) + '.' +
QUOTENAME(name) + ';'
FROM sys.tables;
SQL Fiddle
Neither of the other questions seem to have tried to address the all objects part of the question.
I'm amazed you have to roll your own with this - I expected there to be a drop schema blah cascade. Surely every single person who sets up a dev server will have to do this and having to do some meta-programming before being able to do normal programming is seriously horrible. Anyway... rant over!
I started looking at some of these articles as a way to do it by clearing out a schema: There's an old article about doing this, however the tables mentioned on there are now marked as deprecated. I've also looked at the documentation for the new tables to help understand what is going on here.
There's another answer and a great dynamic sql resource it links to.
After looking at all this stuff for a while it just all seemed a bit too messy.
I think the better option is to go for
ALTER DATABASE 'blah' SET SINGLE_USER WITH ROLLBACK IMMEDIATE
drop database 'blah'
create database 'blah'
instead. The extra incantation at the top is basically to force drop the database as mentioned here
It feels a bit wrong but the amount of complexity involved in writing the drop script is a good reason to avoid it I think.
If there seem to be problems with dropping the database I might revisit some of the links and post another answer
try this with sql2012 or above,
this script may help to delete all objects by selected schema
Note: below script for dbo schema for all objects but you may change in very first line #MySchemaName
DECLARE #MySchemaName VARCHAR(50)='dbo', #sql VARCHAR(MAX)='';
DECLARE #SchemaName VARCHAR(255), #ObjectName VARCHAR(255), #ObjectType VARCHAR(255), #ObjectDesc VARCHAR(255), #Category INT;
DECLARE cur CURSOR FOR
SELECT (s.name)SchemaName, (o.name)ObjectName, (o.type)ObjectType,(o.type_desc)ObjectDesc,(so.category)Category
FROM sys.objects o
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
INNER JOIN sysobjects so ON so.name=o.name
WHERE s.name = #MySchemaName
AND so.category=0
AND o.type IN ('P','PC','U','V','FN','IF','TF','FS','FT','PK','TT')
OPEN cur
FETCH NEXT FROM cur INTO #SchemaName,#ObjectName,#ObjectType,#ObjectDesc,#Category
SET #sql='';
WHILE ##FETCH_STATUS = 0 BEGIN
IF #ObjectType IN('FN', 'IF', 'TF', 'FS', 'FT') SET #sql=#sql+'Drop Function '+#MySchemaName+'.'+#ObjectName+CHAR(13)
IF #ObjectType IN('V') SET #sql=#sql+'Drop View '+#MySchemaName+'.'+#ObjectName+CHAR(13)
IF #ObjectType IN('P') SET #sql=#sql+'Drop Procedure '+#MySchemaName+'.'+#ObjectName+CHAR(13)
IF #ObjectType IN('U') SET #sql=#sql+'Drop Table '+#MySchemaName+'.'+#ObjectName+CHAR(13)
--PRINT #ObjectName + ' | ' + #ObjectType
FETCH NEXT FROM cur INTO #SchemaName,#ObjectName,#ObjectType,#ObjectDesc,#Category
END
CLOSE cur;
DEALLOCATE cur;
SET #sql=#sql+CASE WHEN LEN(#sql)>0 THEN 'Drop Schema '+#MySchemaName+CHAR(13) ELSE '' END
PRINT #sql
EXECUTE (#sql)
I do not know wich version of Sql Server are you using, but assuming that is 2008 or later, maybe the following command will be very useful (check that you can drop ALL TABLES in one simple line):
sp_MSforeachtable "USE DATABASE_NAME DROP TABLE ?"
This script will execute DROP TABLE .... for all tables from database DATABASE_NAME. Is very simple and works perfectly. This command can be used for execute other sql instructions, for example:
sp_MSforeachtable "USE DATABASE_NAME SELECT * FROM ?"
Related
I have almost 150 databases with all the same tables. I know its bad but I don't have control over it. I'm trying to improve performance with some indexes. I know what the indexes should be but I need to build them on the same tables in every database. Is there a way to do this bsides creating them all separately?
I had a similar situation a while back so I came up with this code. You can use dynamic SQL with sp_MSforeachdb to loop through your databases. I've excluded the system databases below but you can include/exclude databases as you like in that first IF.
This code will check each database for your specific table as well as checking to see if that index already exists on that table. If not, it creates it. I included a RAISERROR to show the progress through the databases in SSMS messages. Just change the table/index names below and update the CREATE INDEX statement as appropriate for you.
DECLARE #command varchar(1000)
SELECT #command = 'IF ''?'' NOT IN(''master'', ''model'', ''msdb'', ''tempdb'')
BEGIN USE ?
EXEC(''
DECLARE #DB VARCHAR(200)
SET #DB = DB_NAME()
RAISERROR (#DB, 10, 1) WITH NOWAIT
IF OBJECT_ID(''''dbo.TableName'''', ''''U'''') IS NOT NULL
BEGIN
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name=''''IX_TableName'''' AND object_id = OBJECT_ID(''''TableName''''))
BEGIN
CREATE INDEX [IX_TableName] ON TableName (indexColumn)
END
END
'') END'
EXEC sp_MSforeachdb #command
In an attempt to the query
UPDATE sys.columns
SET user_type_id = 106
WHERE object_id in (select object_id from sys.objects where type = 'U') and user_type_id = 108
I'm getting the error:
Msg 259, Level 16, State 1, Line 1
Ad hoc updates to system catalogs are not allowed.
Is there a way to get around this? In this case, I'm looking to change the types of all decimal fields of all the tables in the database.
Can do this "externally"-- without direct tampering with sys.* tables (haven't yet pinned down how-to though), but I'm looking to know whether I can update the sys.* tables -- and if so, which ones, when/how?
// =========================
EDIT:
would i be able to get any "deeper" than alter table... if i had full privileges for db access?
not sure what kind of privileges i have now, but would look into it.
These tables are informational only. I want to make this clear: the sys.* and INFORMATION_SCHEMA.* views exist to provide schema information from the database engine in a useful format. They do not represent the actual schema of the database*, and modifying them is thus impossible. The only way to change your schema is to use DDL (Data Definition Language) statements, such as ALTER TABLE.
In your case, you can use a cursor to iterate through all columns with the wrong type, generate SQL statements to correct that, and execute them dynamically. Here's a skeleton of how that would look:
DECLARE column_cursor CURSOR FOR
SELECT schemas.name AS schema_name,
objects.name AS table_name,
columns.name AS column_name
FROM sys.columns
JOIN sys.objects
ON objects.object_id = columns.object_id
JOIN sys.schemas
ON schemas.schema_id = objects.schema_id
WHERE objects.type = 'U'
AND columns.user_type_id = 108
DECLARE #schema_name VARCHAR(255)
DECLARE #table_name VARCHAR(255)
DECLARE #column_name VARCHAR(255)
OPEN column_cursor
FETCH NEXT FROM column_cursor INTO #schema_name, #table_name, #column_name
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #sql VARCHAR(MAX)
-- TODO: modify to change to the actual type, scale and precision you want; also you may need to adjust for NOT NULL constraints, default constraints and foreign keys (all exercises for the reader)
SET #sql = 'ALTER TABLE ' + QUOTENAME(#schema_name) + '.' + QUOTENAME(#table_name) + ' CHANGE COLUMN ' + QUOTENAME(#column_name) + ' DECIMAL(12, 2)'
EXEC(#sql)
FETCH NEXT FROM column_cursor INTO #schema_name, #table_name, #column_name
END
CLOSE column_cursor
DEALLOCATE column_cursor
Because of the potential increase in complexity for dealing with constraints and keys, I'd recommend either updating the columns manually, building the ALTER TABLE statements manually, dumping your schema to script, updating that and recreating the tables and objects, or looking for a 3rd party tool that does this kind of thing (I don't know of any).
*For the sys.* views, at least, it's possible that they closely represent the underlying data structures, though I think there's still some abstraction. INFORMATION_SCHEMA is ANSI-defined, so it is unlikely to match the internal structures of any database system out there.
I have many triggers for which I'd like to build a list of table using a wildcard, then update the existing triggers on them by adding some column names to the trigger. The column names will be the same in each trigger, but I'm not clear how build the list of tables or how to loop through the list in a single alter trigger statement. I assume I'll have to use a cursor....
There is no magic wand to say "add this code to all the triggers" (or any other object type, for that matter).
For many object types, for batch editing you can quickly generate a script for multiple objects using Object Explorer Details and sorting and/or filtering within that view. For example, if you highlight "Stored Procedures" in Object Explorer, they're all listed in Object Explorer Details, and you can select multiple objects, right-click, and Script Stored Procedure as > CREATE To >
Since triggers are nested under tables, there isn't a handy way to do this (nor are triggers an entity type you can select when you right-click a database and choose Tasks > Generate Scripts). But you can pull the scripts from the metadata quite easily (you'll want Results to Text in Management Studio when running this):
SET NOCOUNT ON;
SELECT OBJECT_DEFINITION([object_id])
+ CHAR(13) + CHAR(10) + 'GO' + CHAR(13) + CHAR(10)
FROM sys.triggers
WHERE type = 'TR';
You can take the output, copy and paste it into the top pane, then once you have added your new code to each trigger, you'll have to do a little more work to do, e.g. search/replace 'CREATE TRIGGER' for 'ALTER TRIGGER'. You could do that as part of the query too, but it relies on the creator(s) having consistent coding conventions. Since some triggers might look like this...
create trigger
... you may have to massage some by hand.
You can also filter the query above if you are only interested in a certain set of tables. For example, to only alter triggers associated with tables that start with Sales you could say:
AND OBJECT_NAME(parent_id) LIKE N'Sales%';
Or only for tables in the Person schema:
AND OBJECT_SCHEMA_NAME(parent_id) = N'Person';
Anyway once you have made all necessary adjustments to the script, you can just run it. A lot easier than expanding every single table and generating a script for those triggers.
In addition to Aarons suggestion, which worked great on a bunch of complex triggers with inconsistent object naming convention, I then attempted to cook something up so I'd remember what I did in 3 months. Enjoy. Create or alter the SP then execute with no params.
CREATE PROCEDURE SP_ALTER_CONTOUR_TRIGS
--sp to bulk edit many triggers at once
--NO ERROR HANDLING!
AS
DECLARE
#sql VARCHAR(500),
#tableName VARCHAR(128),
#triggerName VARCHAR(128),
#tableSchema VARCHAR(128)
DECLARE triggerCursor CURSOR
FOR
SELECT
so_tr.name AS TriggerName,
so_tbl.name AS TableName,
t.TABLE_SCHEMA AS TableSchema
FROM
sysobjects so_tr
INNER JOIN sysobjects so_tbl ON so_tr.parent_obj = so_tbl.id
INNER JOIN INFORMATION_SCHEMA.TABLES t
ON
t.TABLE_NAME = so_tbl.name
WHERE
--here's where you want to build filters to make sure you're
--targeting the trigs you want edited
--BE CAREFUL!
--test the select statement first against sysobjects
--to see that it returns what you expect
so_tr.type = 'TR'
and so_tbl.name like '%contours'
and so_tr.name like'%location_id'
ORDER BY
so_tbl.name ASC,
so_tr.name ASC
OPEN triggerCursor
FETCH NEXT FROM triggerCursor
INTO #triggerName, #tableName, #tableSchema
WHILE ( ##FETCH_STATUS = 0 )
BEGIN
--insert alter statement below
--watch out for cr returns and open and close qoutes!
--seems to act finicky if you don't use schema-bound naming convention
SET #sql = '
ALTER TRIGGER ['+ #tableSchema +'].['
+ #triggerName + '] ON ['+ #tableSchema +'].['
+ #tableName + ']
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT ['+ #tableSchema +'].['+ #tableName + ']
(OBJECTID, Contour, Type, Shape, RuleID, Override)
SELECT
a.OBJECTID, a.Contour, a.Type, a.Shape, a.RuleID, a.Override
FROM
(SELECT
OBJECTID, Contour, Type, Shape, RuleID, Override
FROM inserted)
AS a
END
'
PRINT 'Executing Statement - '+ #sql
EXECUTE ( #sql )
FETCH NEXT FROM triggerCursor
INTO #triggerName, #tableName, #tableSchema
END
CLOSE triggerCursor
DEALLOCATE triggerCursor
Actually, this is a 2 part question.
Is it possible to use some sort of functionality to search through every stored procedure for a string and possibly replace it, like a standard Find/Replace function?
If you have all your stored procedure code include the full database path like this [db1].[dbo].[table1] and you change the database name to [db2] is there a way for SQL Server to automatically update all the code from [db1] tables to [db2]? Or does it have to be done manually?
From the Object Explorer Details window in SSMS, open the stored procedures folder. Select all the objects (you can multi-select from this window, which is pretty much the only purpose of the Object Explorer Details window) and right click, choosing to script as DROP and CREATE. You can now do a search/replace on this, replacing all you need in one go before executing it.
Edit: I've blogged about this solution.
Late one but hopefully useful.
There is a free search tool from ApexSQL that can find and rename objects in database.
They say it has a smart rename option that will find/replace all occurrences of some object such as table, function or stored procedure.
I have to add that I haven’t used the rename functionality but I can confirm that search is working quite well.
Also I’m not affiliated with ApexSQL but I do use their tools.
To search: if you need to find database objects (e.g. tables, columns, triggers) by name - 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?
This tool doesn't support replacing text, however - but even just being able to find all the relevant stored procedures (or other DB objects) is very helpful indeed!
Export all SPs to file. Use your favourite text editing tool to search/replace. Update database by executing the script (as long as you do not rename procedures).
If you explicitly define the full database path, you need to manually (see above) update the stored procedures. If you do not include the database name, or use a linked server or similar, no changes are necessary.
Stored procedures cannot be updated in place without first scripting them out as ALTER PROCEDURE statements (or DROP/CREATE, but I prefer ALTER PROCEDURE..more on that in a moment). The good news is, you can script all the procedures to a single file through SSMS. The DDL statements will initially be CREATE PROCEDURE, which you'll want to replace with ALTER PROCEDURE, along with your other changes.
While you could alternatively script the procedures as DROP/CREATE, I don't like doing this for a large number of scripts because it tends to cause dependency errors.
As for part 2 of your question, you'll need to edit any database path changes manually through the script.
I found this script where you can define search for and replace by text and simply run it to get text replaced in all procedures at once. I hope this will help you in bulk.
-- set "Result to Text" mode by pressing Ctrl+T
SET NOCOUNT ON
DECLARE #sqlToRun VARCHAR(1000), #searchFor VARCHAR(100), #replaceWith VARCHAR(100)
-- text to search for
SET #searchFor = '[MY-SERVER]'
-- text to replace with
SET #replaceWith = '[MY-SERVER2]'
-- this will hold stored procedures text
DECLARE #temp TABLE (spText VARCHAR(MAX))
DECLARE curHelp CURSOR FAST_FORWARD
FOR
-- get text of all stored procedures that contain search string
-- I am using custom escape character here since i need to espape [ and ] in search string
SELECT DISTINCT 'sp_helptext '''+OBJECT_SCHEMA_NAME(id)+'.'+OBJECT_NAME(id)+''' '
FROM syscomments WHERE TEXT LIKE '%' + REPLACE(REPLACE(#searchFor,']','\]'),'[','\[') + '%' ESCAPE '\'
ORDER BY 'sp_helptext '''+OBJECT_SCHEMA_NAME(id)+'.'+OBJECT_NAME(id)+''' '
OPEN curHelp
FETCH next FROM curHelp INTO #sqlToRun
WHILE ##FETCH_STATUS = 0
BEGIN
--insert stored procedure text into a temporary table
INSERT INTO #temp
EXEC (#sqlToRun)
-- add GO after each stored procedure
INSERT INTO #temp
VALUES ('GO')
FETCH next FROM curHelp INTO #sqlToRun
END
CLOSE curHelp
DEALLOCATE curHelp
-- find and replace search string in stored procedures
-- also replace CREATE PROCEDURE with ALTER PROCEDURE
UPDATE #temp
SET spText = REPLACE(REPLACE(spText,'CREATE PROCEDURE', 'ALTER PROCEDURE'),#searchFor,#replaceWith)
SELECT spText FROM #temp
-- now copy and paste result into new window
-- then make sure everything looks good and run
GO
Here is the reference link :
http://www.ideosity.com/ourblog/post/ideosphere-blog/2013/06/14/how-to-find-and-replace-text-in-all-stored-procedures
You can search the text of the stored procedure definitions using this
SELECT
Name
FROM
sys.procedures
WHERE
OBJECT_DEFINITION(OBJECT_ID) LIKE '%YourSearchText%'
Replacing is generally a bad idea, since you don't know the context of the text you'll find in the stored procedures. It probably is possible though via Powershell scripting.
I prefer this solution to any others, since I'm comfortable writing queries- so finding text in all stored procs, that are in schema (x) and database (y) and names that start with (z) is quite an easy and intuitive query.
Here's one I wrote today to help with a server upgrade project.
Searches all stored procs and views in all user databases on a server, and automatically replaces the search string with another. Ideal for changing hard-coded linked server names and the like:
set nocount on
if OBJECT_ID('tempdb..#dbs') is not null
drop table #dbs
if OBJECT_ID('tempdb..#objects') is not null
drop table #objects
declare #find as nvarchar(128) = 'Monkey'
declare #replace as nvarchar(128) = 'Chimp'
declare #SQL as nvarchar(max)
declare #current_db as sysname
declare #current_schema as sysname
declare #current_object as sysname
declare #current_type as char(2)
declare #current_ansi as bit
declare #current_quot as bit
declare #fullname as sysname
declare #preamble as nvarchar(128)
create table #objects
(
dbname sysname,
schemaname sysname,
objname sysname,
objtype char(2),
ansinulls bit,
quotedidentifier bit
)
create unique clustered index i on #objects (dbname, schemaname, objname)
select [name] into #dbs
from master.sys.databases
where [name] not in ('master','tempdb','model','msdb','ReportServer','ReportServerTempDB', 'SSISDB')
declare db_cursor cursor for select [name] from #dbs order by [name]
open db_cursor
fetch next from db_cursor into #current_db
while ##FETCH_STATUS = 0
begin
set #SQL = 'insert into #objects select ''' + #current_db + ''', s.[name], o.[name], o.[type], m.uses_ansi_nulls, m.uses_quoted_identifier from ' + #current_db + '.sys.sql_modules as m '
+ 'join ' + #current_db + '.sys.objects AS o ON m.object_id = o.object_id '
+ 'join ' + #current_db + '.sys.schemas AS s ON o.schema_id = s.schema_id '
+ 'where m.definition like ''%' + #find + '%'' and type in (''P'', ''V'') and is_ms_shipped = 0 order by s.[name], o.[name]'
exec sp_executeSQL #SQL
fetch next from db_cursor into #current_db
end
close db_cursor
deallocate db_cursor
declare obj_cursor cursor for select dbname, schemaname, objname, objtype, ansinulls, quotedidentifier from #objects order by dbname, objname
open obj_cursor
fetch next from obj_cursor into #current_db, #current_schema, #current_object, #current_type, #current_ansi, #current_quot
while ##FETCH_STATUS = 0
begin
set #fullname = #current_db + '.' + #current_schema + '.' + #current_object
set #preamble = CASE WHEN #current_ansi = 1 THEN 'SET ANSI_NULLS ON' ELSE 'SET ANSI_NULLS OFF' END + '; '
+ CASE WHEN #current_quot = 1 THEN 'SET QUOTED_IDENTIFIER ON' ELSE 'SET QUOTED_IDENTIFIER OFF' END + '; '
print 'Altering ' + #fullname
if #current_type = 'P'
begin
set #SQL = 'use ' + #current_db + '; ' + #preamble + 'declare #newproc nvarchar(max);'
+ 'set #newproc = REPLACE(REPLACE(OBJECT_DEFINITION(OBJECT_ID(''' + #fullname + ''')), ''' + #find + ''', ''' + #replace + '''), ''CREATE PROCEDURE'', ''ALTER PROCEDURE''); '
+ 'exec sp_executeSQL #newproc'
exec sp_executeSQL #SQL
end
if #current_type = 'V'
begin
set #SQL = 'use ' + #current_db + '; ' + #preamble + 'declare #newproc nvarchar(max);'
+ 'set #newproc = REPLACE(REPLACE(OBJECT_DEFINITION(OBJECT_ID(''' + #fullname + ''')), ''' + #find + ''', ''' + #replace + '''), ''CREATE VIEW'', ''ALTER VIEW''); '
+ 'exec sp_executeSQL #newproc'
exec sp_executeSQL #SQL
end
fetch next from obj_cursor into #current_db, #current_schema, #current_object, #current_type, #current_ansi, #current_quot
end
close obj_cursor
deallocate obj_cursor
It also handles idiosyncratic ANSI_NULL and QUOTED_IDENTIFIER settings, and can be extended to handle the various types of function.
Be careful though! With great power comes great responsibility...
Update
I just realized the link in David's answer included the search function. again, it's a great answer.
David Atkinson's answer is great, just want to add the search part. (not sure when the search was added in SSMS, my version is SSMS V17.9.1)
Instead of selecting stored procedures one by one, I can do a search.
The search takes a wildcard, similar to 'like' in TSQL
There's no way to do this with built-in functionality. While it doesn't help you today, I'd suggest changing all of your references to synonyms while you're in there. That way, when this happens again in the future (and it will happen again), all of your external references are in one place and easily updated. Incidentally, I have a blog post on the latter.
I just run this code to find a specific text in all stored procedures:
SELECT DISTINCT
o.name AS Object_Name,
o.type_desc
FROM sys.sql_modules m
INNER JOIN
sys.objects o
ON m.object_id = o.object_id
WHERE m.definition Like '%textToFind%'
or m.definition Like '%\[ifTextIsAColNameWithBrackets\]%' ESCAPE '\';
If you have downtime available.
Go into "Generate scripts" and generate 'create' scripts for all of your sprocs you want to edit.
Replace the text in the script and just drop and re-create all of them.
Hmm, dropping and rebuilding all procedures worked, unfortunately it crashed the SQL server upon which the SCADA for a rather large factory relied.
It saved a bit of effort editing them individually and the factory was only stalled til I rebooted the server.
But exercise some caution methinks. I was fair crapping myself for a moment there.
How do you force a rename???
Rename failed for Table 'dbo.x. (Microsoft.SqlServer.Smo)
For help, click: http://go.microsoft.com/fwlink?ProdName=Microsoft+SQL+Server&ProdVer=10.0.2531.0+((Katmai_PCU_Main).090329-1045+)&EvtSrc=Microsoft.SqlServer.Management.Smo.ExceptionTemplates.FailedOperationExceptionText&EvtID=Rename+Table&LinkId=20476
An exception occurred while executing a Transact-SQL statement or batch. (Microsoft.SqlServer.ConnectionInfo)
Object '[dbo].[x]' cannot be renamed because the object participates in enforced dependencies. (Microsoft SQL Server, Error: 15336)
For help, click: http://go.microsoft.com/fwlink?ProdName=Microsoft+SQL+Server&ProdVer=09.00.4035&EvtSrc=MSSQLServer&EvtID=15336&LinkId=20476
Find the "enforced dependencies", then remove or disable them.
By "enforced dependencies", it means Schema binding, so you'll have to look specifically for that.
Here's a query to look for schema binding references to your object:
select o.name as ObjName, r.name as ReferencedObj
from sys.sql_dependencies d
join sys.objects o on o.object_id=d.object_id
join sys.objects r on r.object_id=d.referenced_major_id
where d.class=1
AND r.name = #YourObjectName
As I noted in the comments, there is no way to FORCE-ibly override Schema Binding. When you use Schema Binding, you are explicitly saying "Do not let me or anyone else override this." The only way around Schema Binding is to undo it, and that's intentional.
I had the same issue , my problem was that i has a COMPUTED FIELD using the column i was trying to rename.
by running the query from the selected answer i was able to tell that had enforced dependencies, but i was not able to see exactly what was the problem
Try this:
/*
Example 1: Rename a table dbo.MyTable -> dbo.YourTable
EXEC dbo.USP_DROP_ENFORCED_DEPENDENCIES #SchemaName=N'dbo', #EntityName=N'MyTable', #Debug=1;
EXEC sp_rename N'dbo.MyTable', N'YourTable', N'OBJECT'
Example 2: Rename a column dbo.MyTable.MyColumn -> dbo.MyTable.YourColumn
EXEC dbo.USP_DROP_ENFORCED_DEPENDENCIES #SchemaName=N'dbo', #EntityName=N'MyTable', #ColumnName=N'MyColumn' #Debug=1;
EXEC sp_rename N'dbo.MyTable.MyColumn', N'YourColumn', N'COLUMN'
*/
CREATE Procedure dbo.USP_DROP_ENFORCED_DEPENDENCIES
(
#SchemaName sysname = 'dbo',
#EntityName sysname,
#ColumnName sysname = NULL,
#Debug bit = 0
)
AS
BEGIN
SET NOCOUNT ON;
SET ROWCOUNT 0;
DECLARE #ReferencingEntitySchema sysname, #ReferencingEntityName sysname, #ReferencingEntityType nvarchar(8), #SqlScript nvarchar(512);
DECLARE ReferencingEntitiesCursor CURSOR LOCAL FORWARD_ONLY
FOR
SELECT OBJECT_SCHEMA_NAME(dep.referencing_id) AS [schema]
,referencing_entity.name
,CASE referencing_entity.type
WHEN 'V' THEN N'VIEW'
ELSE /*IF, FN, TF*/ N'FUNCTION'
END as [type]
FROM sys.sql_expression_dependencies AS dep
INNER JOIN sys.objects AS referencing_entity
ON dep.referencing_id = referencing_entity.object_id
WHERE dep.referenced_entity_name = #EntityName
AND dep.referenced_schema_name = #SchemaName
AND is_schema_bound_reference = 1
AND ((#ColumnName IS NULL AND dep.referenced_minor_id = 0) OR COL_NAME(dep.referenced_id, dep.referenced_minor_id) = #ColumnName)
OPEN ReferencingEntitiesCursor
FETCH NEXT FROM ReferencingEntitiesCursor
INTO #ReferencingEntitySchema, #ReferencingEntityName, #ReferencingEntityType;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC dbo.USP_DROP_ENFORCED_DEPENDENCIES #SchemaName=#ReferencingEntitySchema, #EntityName=#ReferencingEntityName, #Debug=#Debug;
--The goal is to produce the following script:
/*
DROP FUNCTION dbo.UFN_SOME_FUNCTION;
OR
DROP VIEW dbo.UFN_SOME_VIEW;
*/
SET #SqlScript = N'DROP ' + #ReferencingEntityType + N' ' + #ReferencingEntitySchema + '.' + #ReferencingEntityName;
IF(#Debug = 1)
RAISERROR (#SqlScript, 0/*severity*/, 0/*state*/) WITH NOWAIT;
EXEC (#SqlScript);
FETCH NEXT FROM ReferencingEntitiesCursor
INTO #ReferencingEntitySchema, #ReferencingEntityName, #ReferencingEntityType;
END
CLOSE ReferencingEntitiesCursor;
DEALLOCATE ReferencingEntitiesCursor;
END
GO
In the SQL Server Object Browser, right-click on the table with the issue and select View Dependencies. Next in the view listed, Right-click (view) and select SCRIPT to CREATE VIEW in New SQL Query Editor window, then remove WITH SCHEMABINDING from the CREATE VIEW t-sql script and run the revised CREATE VIEW t-sql. This unlinks the schema dependency from the table. I was able to recreate the table at this point (DROP, RENAME, etc).
Note:
Schema binding can occur on functions and other objects in your db.
Use of View Dependencies on the object throwing the error is essential
to fix the issue.
BTW:
I originally added schema binding to enable view indexing. Keeping a
good index on the underlying table(s) may mitigate the performance hit
of not having one on the view.
View Dependencies
More on Schema Binding
I had an issue like this. I dropped constraints on this DB object, renamed the DB object then recreated these constraints. This solved my problem.
I used this script to get dependent view with schemabingings:
select distinct o.name, o.type from sys.sql_expression_dependencies dep inner join sys.objects o on dep.referencing_id=o.object_id where referenced_id = OBJECT_ID(<your dependency owner object>) and o.type = 'V'