Programmatically set the permissions on a table - sql

I want to programmatically set the permissions (i.e. GRANT) on a newly created table. I was hoping to get SQL Server to show me the script for that by going to another table in the database and doing a right-click and then "Script Table as" but I don't see the option for GRANT underneath that.
Is it possible to get SQL Server to show me the script for this?

Look around some more. The simple version is to use the dialog where you set permissions. E.g.,
A more general and advanced approach - with far more options - is to use the script feature at the database level. On your database, rt click and select , , and then run through the wizard to select your table and the scripting options you want. Be sure to click the Advanced button in the scripting options tab - where you will see "object-level permissions" (off by default).

Too long to comment.
GRANT <n> ON YourDatabase.YourSchema.YourTable TO YourSpecificUser
In this case, since it's a table <n> can be one of the following:
DELETE
INSERT
REFERENCES
SELECT
UPDATE
Note, if a user has a fixed database role, they could have more access than you explicitly grant them. Read more about GRANT Object Permissions.
Of note, to return a list of permissions on a table, you can use sp_table_privileges
sp_table_privileges #table_name = 'YourTable'
You can capture these results and then loop through them to build a dynamic sql query.
Replace the script below with your TableName and what ever your NewTableName is. When you are satisfied with the print out, you can uncomment the exec(#sql) to execute the code that's printed.
if object_id('tempdb..#priv') is not null
drop table #priv
create table #priv( ID int identity (1,1)
,TABLE_QUALIFIER varchar(64)
,TABLE_OWNER VARCHAR(64)
,TABLE_NAME VARCHAR(64)
,GRANTOR VARCHAR(64)
,GRANTEE VARCHAR(64)
,PRIVILEGE VARCHAR(64)
,IS_GRANTABLE VARCHAR(8))
insert into #priv
exec sp_table_privileges #table_name = 'YourTableName'
declare #i int = 1
declare #max int = (select max(id) from #priv)
declare #sql varchar(max) = ''
while (#i <= #max)
begin
set #sql = #sql + (select ' GRANT ' + stuff(PRIVILEGE,1,0,' ') + ' ON ' + stuff(TABLE_NAME,1,0,' ') + ' TO ' + stuff(GRANTEE,1,0,' ') + char(13) + ' GO ' + char(13) from #priv where ID = #i)
set #i = #i + 1
end
print(#sql)
set #sql = replace(#sql,'YourTableName','NewTableName')
print(#sql)
--exec(#sql)

Related

How to alter user defined data types in SQL Server tables and SP [duplicate]

I created few user defined types in my database as below
CREATE TYPE [dbo].[StringID] FROM [nvarchar](20) NOT NULL
and assigned them to various tables. The tables in my database are in various schemas (not only dbo)
But I realized I need bigger field, and I need to alter, e.g increase from [nvarchar](20) to [nvarchar](50), but there is no ALTER TYPE statement.
I need a script that uses a temp table/cursor whatever and saves all the tables and fields where my type is used. Then change existing fields to base type - e.g. from CustID [StringID] to CustID [nvarchar(20)].
Drop the user type and recreate it with new type - e.g. nvarchar(50)
and finally set back fields to user type
I do not have rules defined on types, so don't have to drop rules and re-add them.
Any help is appreciated.
This is what I normally use, albeit a bit manual:
/* Add a 'temporary' UDDT with the new definition */
exec sp_addtype t_myudt_tmp, 'numeric(18,5)', NULL
/* Build a command to alter all the existing columns - cut and
** paste the output, then run it */
select 'alter table dbo.' + TABLE_NAME +
' alter column ' + COLUMN_NAME + ' t_myudt_tmp'
from INFORMATION_SCHEMA.COLUMNS
where DOMAIN_NAME = 't_myudt'
/* Remove the old UDDT */
exec sp_droptype t_mydut
/* Rename the 'temporary' UDDT to the correct name */
exec sp_rename 't_myudt_tmp', 't_myudt', 'USERDATATYPE'
We are using the following procedure, it allows us to re-create a type from scratch, which is "a start". It renames the existing type, creates the type, recompiles stored procs and then drops the old type. This takes care of scenarios where simply dropping the old type-definition fails due to references to that type.
Usage Example:
exec RECREATE_TYPE #schema='dbo', #typ_nme='typ_foo', #sql='AS TABLE([bar] varchar(10) NOT NULL)'
Code:
CREATE PROCEDURE [dbo].[RECREATE_TYPE]
#schema VARCHAR(100), -- the schema name for the existing type
#typ_nme VARCHAR(128), -- the type-name (without schema name)
#sql VARCHAR(MAX) -- the SQL to create a type WITHOUT the "CREATE TYPE schema.typename" part
AS DECLARE
#scid BIGINT,
#typ_id BIGINT,
#temp_nme VARCHAR(1000),
#msg VARCHAR(200)
BEGIN
-- find the existing type by schema and name
SELECT #scid = [SCHEMA_ID] FROM sys.schemas WHERE UPPER(name) = UPPER(#schema);
IF (#scid IS NULL) BEGIN
SET #msg = 'Schema ''' + #schema + ''' not found.';
RAISERROR (#msg, 1, 0);
END;
SELECT #typ_id = system_type_id FROM sys.types WHERE UPPER(name) = UPPER(#typ_nme);
SET #temp_nme = #typ_nme + '_rcrt'; -- temporary name for the existing type
-- if the type-to-be-recreated actually exists, then rename it (give it a temporary name)
-- if it doesn't exist, then that's OK, too.
IF (#typ_id IS NOT NULL) BEGIN
exec sp_rename #objname=#typ_nme, #newname= #temp_nme, #objtype='USERDATATYPE'
END;
-- now create the new type
SET #sql = 'CREATE TYPE ' + #schema + '.' + #typ_nme + ' ' + #sql;
exec sp_sqlexec #sql;
-- if we are RE-creating a type (as opposed to just creating a brand-spanking-new type)...
IF (#typ_id IS NOT NULL) BEGIN
exec recompile_prog; -- then recompile all stored procs (that may have used the type)
exec sp_droptype #typename=#temp_nme; -- and drop the temporary type which is now no longer referenced
END;
END
GO
CREATE PROCEDURE [dbo].[recompile_prog]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #v TABLE (RecID INT IDENTITY(1,1), spname sysname)
-- retrieve the list of stored procedures
INSERT INTO
#v(spname)
SELECT
'[' + s.[name] + '].[' + items.name + ']'
FROM
(SELECT sp.name, sp.schema_id, sp.is_ms_shipped FROM sys.procedures sp UNION SELECT so.name, so.SCHEMA_ID, so.is_ms_shipped FROM sys.objects so WHERE so.type_desc LIKE '%FUNCTION%') items
INNER JOIN sys.schemas s ON s.schema_id = items.schema_id
WHERE is_ms_shipped = 0;
-- counter variables
DECLARE #cnt INT, #Tot INT;
SELECT #cnt = 1;
SELECT #Tot = COUNT(*) FROM #v;
DECLARE #spname sysname
-- start the loop
WHILE #Cnt <= #Tot BEGIN
SELECT #spname = spname
FROM #v
WHERE RecID = #Cnt;
--PRINT 'refreshing...' + #spname
BEGIN TRY -- refresh the stored procedure
EXEC sp_refreshsqlmodule #spname
END TRY
BEGIN CATCH
PRINT 'Validation failed for : ' + #spname + ', Error:' + ERROR_MESSAGE();
END CATCH
SET #Cnt = #cnt + 1;
END;
END
there's a good example of a more comprehensive script here
It's worth noting that this script will include views if you have any. I ran it and instead of exec'ing inline generated a script as the output which I then tweaked and ran.
Also, if you have functions/sprocs using the user defeined types you'll need to drop those before running your script.
Lesson Learned: in future, don't bother with UDTs they're more hassle than they're worth.
SET NOCOUNT ON
DECLARE #udt VARCHAR(150)
DECLARE #udtschema VARCHAR(150)
DECLARE #newudtschema VARCHAR(150)
DECLARE #newudtDataType VARCHAR(150)
DECLARE #newudtDataSize smallint
DECLARE #OtherParameter VARCHAR(50)
SET #udt = 'Name' -- Existing UDDT
SET #udtschema = 'dbo' -- Schema of the UDDT
SET #newudtDataType = 'varchar' -- Data type for te new UDDT
SET #newudtDataSize = 500 -- Lenght of the new UDDT
SET #newudtschema = 'dbo' -- Schema of the new UDDT
SET #OtherParameter = ' NULL' -- Other parameters like NULL , NOT NULL
DECLARE #Datatype VARCHAR(50),
#Datasize SMALLINT
DECLARE #varcharDataType VARCHAR(50)
DECLARE #Schemaname VARCHAR(50),
#TableName VARCHAR(50),
#FiledName VARCHAR(50)
CREATE TABLE #udtflds
(
Schemaname VARCHAR(50),
TableName VARCHAR(50),
FiledName VARCHAR(50)
)
SELECT TOP 1
#Datatype = Data_type,
#Datasize = character_maximum_length
FROM INFORMATION_SCHEMA.COLUMNS
WHERE Domain_name = #udt
AND Domain_schema = #udtschema
SET #varcharDataType = #Datatype
IF #DataType Like '%char%'
AND #Datasize IS NOT NULL
AND ( #newudtDataType <> 'varchar(max)'
OR #newudtDataType <> 'nvarchar(max)'
)
BEGIN
SET #varcharDataType = #varcharDataType + '('
+ CAST(#Datasize AS VARCHAR(50)) + ')'
END
INSERT INTO #udtflds
SELECT TABLE_SCHEMA,
TABLE_NAME,
Column_Name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE Domain_name = #udt
AND Domain_schema = #udtschema
DECLARE #exec VARCHAR(500)
DECLARE alter_cursor CURSOR
FOR SELECT Schemaname,
TableName,
FiledName
FROM #udtflds
OPEN alter_cursor
FETCH NEXT FROM alter_cursor INTO #Schemaname, #TableName, #FiledName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #exec = 'Alter Table ' + #Schemaname + '.' + #TableName
+ ' ALTER COLUMN ' + #FiledName + ' ' + #varcharDataType
EXECUTE ( #exec
)
FETCH NEXT FROM alter_cursor INTO #Schemaname, #TableName, #FiledName
END
CLOSE alter_cursor
SET #exec = 'DROP TYPE [' + #udtschema + '].[' + #udt + ']'
EXEC ( #exec
)
SET #varcharDataType = #newudtDataType
IF #newudtDataType Like '%char%'
AND #newudtDataSize IS NOT NULL
AND ( #newudtDataType <> 'varchar(max)'
OR #newudtDataType <> 'nvarchar(max)'
)
BEGIN
SET #varcharDataType = #varcharDataType + '('
+ CAST(#newudtDataSize AS VARCHAR(50)) + ')'
END
SET #exec = 'CREATE TYPE [' + #newudtschema + '].[' + #udt + '] FROM '
+ #varcharDataType + ' ' + #OtherParameter
EXEC ( #exec
)
OPEN alter_cursor
FETCH NEXT FROM alter_cursor INTO #Schemaname, #TableName, #FiledName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #exec = 'Alter Table ' + #Schemaname + '.' + #TableName
+ ' ALTER COLUMN ' + #FiledName + ' ' + '[' + #newudtschema
+ '].[' + #udt + ']'
EXECUTE ( #exec
)
FETCH NEXT FROM alter_cursor INTO #Schemaname, #TableName, #FiledName
END
CLOSE alter_cursor
DEALLOCATE alter_cursor
SELECT *
FROM #udtflds
DROP TABLE #udtflds
1: http://www.sql-server-performance.com/2008/how-to-alter-a-uddt/ has replaced http://www.sql-server-performance.com/faq/How_to_alter_a%20_UDDT_p1.aspx
The simplest way to do this is through Visual Studio's object explorer, which is also supported in the Community edition.
Once you have made a connection to SQL server, browse to the type, right click and select View Code, make your changes to the schema of the user defined type and click update. Visual Studio should show you all of the dependencies for that object and generate scripts to update the type and recompile dependencies.
As devio says there is no way to simply edit a UDT if it's in use.
A work-round through SMS that worked for me was to generate a create script and make the appropriate changes; rename the existing UDT; run the create script; recompile the related sprocs and drop the renamed version.
The solutions provided here can only be applied if the user defined types are used in table definitions only, and if the UDT columns are not indexed.
Some developers also have SP's and functions using UDT parameters, which is not covered either. (see comments on Robin's link and in the Connect entry)
The Connect entry from 2007 has finally been closed after 3 years:
Thank you for submitting this
suggestion, but given its priority
relative to the many other items in
our queue, it is unlikely that we will
actually complete it. As such, we are
closing this suggestion as “won’t
fix”.
I tried to solve a similiar problem ALTERing XML SCHEMA COLLECTIONS, and the steps seem to mostly apply to ALTER TYPE, too:
To drop a UDT, the following steps are necessary:
If a table column references the UDT, it has to be converted to the underlying type
If the table column has a default constraint, drop the default constraint
If a procedure or function has UDT parameters, the procedure or function has to be dropped
If there is an index on a UDT column, the index has to be dropped
If the index is a primary key, all foreign keys have to be dropped
If there are computed columns based on a UDT column, the computed columns have to be dropped
If there are indexes on these computed columns, the indexes have to be dropped
If there are schema-bound views, functions, or procedures based on tables containing UDT columns, these objects have to be dropped
I ran into this issue with custom types in stored procedures, and solved it with the script below. I didn't fully understand the scripts above, and I follow the rule of "if you don't know what it does, don't do it".
In a nutshell, I rename the old type, and create a new one with the original type name. Then, I tell SQL Server to refresh its details about each stored procedure using the custom type. You have to do this, as everything is still "compiled" with reference to the old type, even with the rename. In this case, the type I needed to change was "PrizeType". I hope this helps. I'm looking for feedback, too, so I learn :)
Note that you may need to go to Programmability > Types > [Appropriate User Type] and delete the object. I found that DROP TYPE doesn't appear to always drop the type even after using the statement.
/* Rename the UDDT you want to replace to another name */
exec sp_rename 'PrizeType', 'PrizeTypeOld', 'USERDATATYPE';
/* Add the updated UDDT with the new definition */
CREATE TYPE [dbo].[PrizeType] AS TABLE(
[Type] [nvarchar](50) NOT NULL,
[Description] [nvarchar](max) NOT NULL,
[ImageUrl] [varchar](max) NULL
);
/* We need to force stored procedures to refresh with the new type... let's take care of that. */
/* Get a cursor over a list of all the stored procedures that may use this and refresh them */
declare sprocs cursor
local static read_only forward_only
for
select specific_name from information_schema.routines where routine_type = 'PROCEDURE'
declare #sprocName varchar(max)
open sprocs
fetch next from sprocs into #sprocName
while ##fetch_status = 0
begin
print 'Updating ' + #sprocName;
exec sp_refreshsqlmodule #sprocName
fetch next from sprocs into #sprocName
end
close sprocs
deallocate sprocs
/* Drop the old type, now that everything's been re-assigned; must do this last */
drop type PrizeTypeOld;
New answer to an old question:
Visual Studio Database Projects handle the drop and recreate process when you deploy changes. It will drop stored procs that use UDDTs and then recreate them after dropping and recreating the data type.
1.Rename the old UDT,
2.Execute query ,
3.Drop the old UDT.
Simple DROP TYPE first then CREATE TYPE again with corrections/alterations?
There is a simple test to see if it is defined before you drop it ... much like a table, proc or function -- if I wasn't at work I would look what that is?
(I only skimmed above too ... if I read it wrong I apologise in advance! ;)

Data purging Delete statement formation

I was just writing a stored procedure and I am stuck badly at one point.
Basically my stored procedure looks like this:
CREATE PROCEDURE [dbo].[DELETEGUIDTESTNEW1]
(#IpApplicationNumber NVARCHAR(50) = NULL)
AS
BEGIN
DECLARE #ApplicationNumber NVARCHAR(20)
SET #ApplicationNumber = (SELECT APPLICATIONNUMBER
FROM CUSTOMERROLE
WHERE CUSTOMERNUMBER = #IpCustomerNumber
AND CUSTOMERVERSIONNUMBER = #IpCustomerVersion)
-- In between I am doing business operation--------------------
INSERT INTO dbo.DeleteTest1(Statements)
VALUES ('Delete from '+#GuidTableName+' where ApplicationNumber =' + #ApplicationNumber)
I will get my parameter at runtime but actual issue is I want to form my delete statements before getting application number and I want form my delete statements in such a way that when I will get my application number I will fetch all delete statement from table and replace #ApplicationNumber by actual application number and will delete records from database.
So basically I want to form delete statements with application number as template and delete records at runtime.
Please help!
Well I have found solution to db purging. To handle runtime GUID situation I published stored procedure from stored procedure.
SELECT #GuidPrimaryTableSpace = #GuidPrimaryTableSpace + DeleteGuidStatement + ';'+ CHAR(13) + CHAR(10)
FROM ##Purge_GuidForeignKeyTablePurgeStatements
SELECT #GuidForeignKeyTableSpace = #GuidForeignKeyTableSpace +'Insert Into #AddressRecordsToPurge (GuidValue, GuidColumn) ( '+ SelectGuidStatement +');'+ CHAR(13) + CHAR(10)
FROM ##Purge_GuidPrimaryTablePurgeStatements
SELECT #DeleteGuidStatementSpace = #DeleteGuidStatementSpace + DeleteGuidValueStatement + ';'+ CHAR(13) + CHAR(10)
FROM ##Purge_GuidTableNames
SET #createProcedureCmd = 'CREATE PROCEDURE MyProc' + ' (#ApplicationNum nvarchar(50),#CustomerNumber nvarchar(50),#CustomerVersionNumber nvarchar(50)) AS ' + ' BEGIN '+
' DECLARE #ApplicationNumber nvarchar(50); SET #ApplicationNumber = #ApplicationNum;
DECLARE #AddressRecordsToPurge TABLE
(
RowID INT NOT NULL PRIMARY KEY IDENTITY(1,1),
GUIDValue Nvarchar(max),
GUIDColumn Nvarchar(max)
)'+ CHAR(13) + CHAR(10) + #GuidForeignKeyTableSpace + #GuidPrimaryTableSpace + #DeleteGuidStatementSpace +' END'
EXEC(#createProcedureCmd)
So here I am forming all select statement first and publishing stored procedure. At runtime when it will hit my published stored procedure, I will first find all guids in temp table and then start my delete.
Thank you anyways for all inputs.

How do I insert values in an idenity column over a linkedServer [duplicate]

I want to use a stored procedure to copy a table from my test database to a linked server with the same ID's / Identity but I can't get it to work..
I've set the IDENTITY_INSERT to ON but it still complains about the ID column.
Here's my procedure:
CREATE PROCEDURE [dbo].[TEST2PROD_CopyUIDataSServer]
AS Begin
declare #sql nvarchar(max)
-- First truncate target table
set #sql = 'EXEC [LINKEDSERVER].tempdb.sys.sp_sqlexec' + char(39)+ 'TRUNCATE Table [ProductManager].dbo.[UIData]' + char(39)+ ';'
---- SET IDENTITY_INSERT ON
set #sql = #sql + 'EXEC [LINKEDSERVER].tempdb.sys.sp_sqlexec' + char(39)+ 'SET IDENTITY_INSERT [ProductManager].[dbo].[UIData] ON' + char(39)+ ';'
---- INSERT UIDATA records from DB1 into linked server DB2
set #sql = #sql + 'WITH TestData as (SELECT * from ProductManager.dbo.UIData UID)' + NCHAR(13)+ 'INSERT INTO [LINKEDSERVER].[ProductManager].[dbo].[UIData]' + NCHAR(13) + 'select * from TestData;'
print #sql
exec (#sql)
end
But when I execute the SP it gives me the following error:
The OLE DB provider "SQLNCLI10" for linked server .... could not INSERT INTO table "[LINKEDSERVER].[ProductManager].[dbo].[UIData]" because of column "Id". The user did not have permission to write to the column.
Linked server properties RPC and RPC out are set to true. I hope someboy can help me out here?
UPDATE: I decided to pull things apart, first I copy the data from the local server to the linked server in a TEMP_TABLE where I don't have to deal with IDENTITY issues.
Then I wrote a stored procedure on the linked / remote server, since I'm not using SELECT * but specify the column list. Chances are this will work from the local server in an SP too but I don't have the time or interest to check it out yet..
USE [ProductManager]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[TEST2PROD_CopyBaseTables]
AS BEGIN
DECLARE #DestTable VARCHAR(50)
DECLARE #DestPath VARCHAR(50)
DECLARE #SrceTable VARCHAR(255)
declare #sql nvarchar(max)
DECLARE #columnList varchar(max)
DECLARE #err int
Begin TRY
declare #comma_delimited_list varchar(4000)
--- FIRST TRY WITH ONE TABLE, EXTENDABLE...
set #comma_delimited_list = 'UIData'
declare #cursor cursor
set #cursor = cursor static for
select * from dbo.Split(#comma_delimited_list,',') a
declare #naam varchar(50)
open #cursor
while 1=1 begin
fetch next from #cursor into #DestTable
if ##fetch_status <> 0 break
--Create tablenames
SET #SrceTable = '[ProductManager].[dbo].TEMP_' + #DestTable
SET #DestPath = '[ProductManager].[dbo].'+ #DestTable
print #srceTable;
print #DestTable;
--Truncate target table
set #sql ='TRUNCATE TABLE '+ #DestPath + ';'
--Insert statement needs column names
set #columnList =''
SELECT #columnList = coalesce(#columnList + '[' + name + '],','') FROM sys.columns Where OBJECT_NAME(OBJECT_ID) = #DestTable
if RIGHT(RTRIM(#columnList),1) = ','
begin
SET #columnList = LEFT(#columnList, LEN(#columnList) - 1)
end
--Transfer data from source table 2 destination
set #sql = #sql + ' SET IDENTITY_INSERT ' + #DestPath + ' ON;' + ' INSERT INTO ' + #DestPath + '(' + #columnList + ') SELECT ' + #columnList + ' FROM ' + #SrceTable
print #sql;
exec (#sql)
end
-- not strictly necessary w/ cursor variables since the will go out of scope like a normal var
close #cursor
deallocate #cursor
End Try
Begin Catch
declare #ErrorMsg nvarchar(MAX);
select #ErrorMsg = ERROR_MESSAGE();
SELECT #err = ##error IF #err <> 0 Return #err
end Catch
END
IDENTITY_INSERT doesn't work with linked servers AFAIK, unless you execute dynamic SQL that includes the SET IDENTITY_INSERT in the batch or have some code (Stored Proc for instance) on the remote server which does that for you.
The IDENTITY_INSERT is per-session (see MSDN) and when you use the remote server this will probably be in a different session from your statement executed via [LINKEDSERVER].tempdb.sys.sp_sqlexec, which causes it to fail as you see it happening.
You can insert an identity value into a table with an identity column on a linked server with the "SWITCH TO" trick.
If you haven't used the "SWITCH TO" trick to add and remove identity on a column, it's very quick, even on large tables!
Conceptually you simply create a new SCHEMA exactly like the table you are wanting to INSERT to without the identity defined. Then switch the table to that SCHEMA and do your INSERT. Then switch back to the SCHEMA with the identity defined.
The sample below has been tested on a linked server in AZURE.
All the caveats of using "SWITCH TO" apply (indexes must be the same, drop and recreate foreign keys, etc)
To test, you can run the full script below on an Linked Azure SQL Server database. You'll need to do a find/replace with [LINKED_SERVER_NAME] and [DATABASE_NAME], replacing with your values. On a non-Azure DB you may need to add "ON PRIMARY" to the table creations.
--Let's setup the example by creating a table with an IDENTITY column on the Linked Server
EXEC('
CREATE TABLE [DATABASE_NAME].[dbo].[Example_Table](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nchar](10) NULL
)
'
) AT [LINKED_SERVER_NAME]
--INSERT some data into the table
INSERT INTO [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table] ([Name]) VALUES ('Travis')
INSERT INTO [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table] ([Name]) VALUES ('Mike')
-- Looks good
SELECT * FROM [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table]
GO
-- Create a TABLE with an identical schema, without the identity defined
EXEC('
CREATE TABLE [DATABASE_NAME].[dbo].[Example_Table_temp](
[ID] [int] NOT NULL,
[Name] [nchar](10) NULL
)
'
) AT [LINKED_SERVER_NAME]
--Now Use the "SWITCH TO" to move the data to the new table
EXEC('
ALTER TABLE [DATABASE_NAME].[dbo].[Example_Table] SWITCH TO [DATABASE_NAME].[dbo].[Example_Table_temp]
'
) AT [LINKED_SERVER_NAME]
--Drop the old table (It should now be empty, but you may want to verify that if you are unsure here)
EXEC('
DROP TABLE [DATABASE_NAME].[dbo].[Example_Table]
'
) AT [LINKED_SERVER_NAME]
--Rename the new table back to the old table name
-- NOTE the lack of database and owner identifiers in the new name
-- NOTE the use of double single qoutes (ESCAPED single quotes)
EXEC('USE [DATABASE_NAME];
EXEC sp_rename ''[DATABASE_NAME].[dbo].Example_Table_temp'',''Example_Table''
'
) AT [LINKED_SERVER_NAME]
-- Now do your IDENTITY INSERTs !!!!
INSERT INTO [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table] (ID,[Name]) VALUES (888,'Travis')
INSERT INTO [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table] (ID,[Name]) VALUES (999,'Mike')
--Verify they got put in
SELECT * FROM [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table]
--Now let's switch it back to our SCHEMA with an IDENTITY
EXEC('
CREATE TABLE [DATABASE_NAME].[dbo].[Example_Table_temp](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nchar](10) NULL
)
ALTER TABLE [DATABASE_NAME].[dbo].[Example_Table] SWITCH TO [DATABASE_NAME].[dbo].[Example_Table_temp]
DROP TABLE [DATABASE_NAME].[dbo].[Example_Table]
EXEC sp_rename ''[DATABASE_NAME].[dbo].Example_Table_temp'',''Example_Table''
'
) AT [LINKED_SERVER_NAME]
--Data is still there
SELECT * FROM [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table]
GO
-- And note you can no longer INSERT the IDENTITY
INSERT INTO [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table] (ID,[Name]) VALUES (45,'Travis')
GO
You need to execute dynamic query Example :
exec [LINKSERVERNAME].[DATABASENAME].[SCHEMANAME].sp_executesql N'Your Query'
If any column set identity the you need to set SET IDENTITY_INSERT TargetTable ON and need to specified the column name. Example:
SET IDENTITY_INSERT TargetTable ON;
INSERT INTO TargetTable(Col1, Col2, Col3)
SELECT Col1, Col2, Col3 FROM SourceTable;
SET IDENTITY_INSERT TargetTable OFF;

Quickest/Easiest way to use Search/Replace through all stored procedures

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.

Alter user defined type in SQL Server

I created few user defined types in my database as below
CREATE TYPE [dbo].[StringID] FROM [nvarchar](20) NOT NULL
and assigned them to various tables. The tables in my database are in various schemas (not only dbo)
But I realized I need bigger field, and I need to alter, e.g increase from [nvarchar](20) to [nvarchar](50), but there is no ALTER TYPE statement.
I need a script that uses a temp table/cursor whatever and saves all the tables and fields where my type is used. Then change existing fields to base type - e.g. from CustID [StringID] to CustID [nvarchar(20)].
Drop the user type and recreate it with new type - e.g. nvarchar(50)
and finally set back fields to user type
I do not have rules defined on types, so don't have to drop rules and re-add them.
Any help is appreciated.
This is what I normally use, albeit a bit manual:
/* Add a 'temporary' UDDT with the new definition */
exec sp_addtype t_myudt_tmp, 'numeric(18,5)', NULL
/* Build a command to alter all the existing columns - cut and
** paste the output, then run it */
select 'alter table dbo.' + TABLE_NAME +
' alter column ' + COLUMN_NAME + ' t_myudt_tmp'
from INFORMATION_SCHEMA.COLUMNS
where DOMAIN_NAME = 't_myudt'
/* Remove the old UDDT */
exec sp_droptype t_mydut
/* Rename the 'temporary' UDDT to the correct name */
exec sp_rename 't_myudt_tmp', 't_myudt', 'USERDATATYPE'
We are using the following procedure, it allows us to re-create a type from scratch, which is "a start". It renames the existing type, creates the type, recompiles stored procs and then drops the old type. This takes care of scenarios where simply dropping the old type-definition fails due to references to that type.
Usage Example:
exec RECREATE_TYPE #schema='dbo', #typ_nme='typ_foo', #sql='AS TABLE([bar] varchar(10) NOT NULL)'
Code:
CREATE PROCEDURE [dbo].[RECREATE_TYPE]
#schema VARCHAR(100), -- the schema name for the existing type
#typ_nme VARCHAR(128), -- the type-name (without schema name)
#sql VARCHAR(MAX) -- the SQL to create a type WITHOUT the "CREATE TYPE schema.typename" part
AS DECLARE
#scid BIGINT,
#typ_id BIGINT,
#temp_nme VARCHAR(1000),
#msg VARCHAR(200)
BEGIN
-- find the existing type by schema and name
SELECT #scid = [SCHEMA_ID] FROM sys.schemas WHERE UPPER(name) = UPPER(#schema);
IF (#scid IS NULL) BEGIN
SET #msg = 'Schema ''' + #schema + ''' not found.';
RAISERROR (#msg, 1, 0);
END;
SELECT #typ_id = system_type_id FROM sys.types WHERE UPPER(name) = UPPER(#typ_nme);
SET #temp_nme = #typ_nme + '_rcrt'; -- temporary name for the existing type
-- if the type-to-be-recreated actually exists, then rename it (give it a temporary name)
-- if it doesn't exist, then that's OK, too.
IF (#typ_id IS NOT NULL) BEGIN
exec sp_rename #objname=#typ_nme, #newname= #temp_nme, #objtype='USERDATATYPE'
END;
-- now create the new type
SET #sql = 'CREATE TYPE ' + #schema + '.' + #typ_nme + ' ' + #sql;
exec sp_sqlexec #sql;
-- if we are RE-creating a type (as opposed to just creating a brand-spanking-new type)...
IF (#typ_id IS NOT NULL) BEGIN
exec recompile_prog; -- then recompile all stored procs (that may have used the type)
exec sp_droptype #typename=#temp_nme; -- and drop the temporary type which is now no longer referenced
END;
END
GO
CREATE PROCEDURE [dbo].[recompile_prog]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #v TABLE (RecID INT IDENTITY(1,1), spname sysname)
-- retrieve the list of stored procedures
INSERT INTO
#v(spname)
SELECT
'[' + s.[name] + '].[' + items.name + ']'
FROM
(SELECT sp.name, sp.schema_id, sp.is_ms_shipped FROM sys.procedures sp UNION SELECT so.name, so.SCHEMA_ID, so.is_ms_shipped FROM sys.objects so WHERE so.type_desc LIKE '%FUNCTION%') items
INNER JOIN sys.schemas s ON s.schema_id = items.schema_id
WHERE is_ms_shipped = 0;
-- counter variables
DECLARE #cnt INT, #Tot INT;
SELECT #cnt = 1;
SELECT #Tot = COUNT(*) FROM #v;
DECLARE #spname sysname
-- start the loop
WHILE #Cnt <= #Tot BEGIN
SELECT #spname = spname
FROM #v
WHERE RecID = #Cnt;
--PRINT 'refreshing...' + #spname
BEGIN TRY -- refresh the stored procedure
EXEC sp_refreshsqlmodule #spname
END TRY
BEGIN CATCH
PRINT 'Validation failed for : ' + #spname + ', Error:' + ERROR_MESSAGE();
END CATCH
SET #Cnt = #cnt + 1;
END;
END
there's a good example of a more comprehensive script here
It's worth noting that this script will include views if you have any. I ran it and instead of exec'ing inline generated a script as the output which I then tweaked and ran.
Also, if you have functions/sprocs using the user defeined types you'll need to drop those before running your script.
Lesson Learned: in future, don't bother with UDTs they're more hassle than they're worth.
SET NOCOUNT ON
DECLARE #udt VARCHAR(150)
DECLARE #udtschema VARCHAR(150)
DECLARE #newudtschema VARCHAR(150)
DECLARE #newudtDataType VARCHAR(150)
DECLARE #newudtDataSize smallint
DECLARE #OtherParameter VARCHAR(50)
SET #udt = 'Name' -- Existing UDDT
SET #udtschema = 'dbo' -- Schema of the UDDT
SET #newudtDataType = 'varchar' -- Data type for te new UDDT
SET #newudtDataSize = 500 -- Lenght of the new UDDT
SET #newudtschema = 'dbo' -- Schema of the new UDDT
SET #OtherParameter = ' NULL' -- Other parameters like NULL , NOT NULL
DECLARE #Datatype VARCHAR(50),
#Datasize SMALLINT
DECLARE #varcharDataType VARCHAR(50)
DECLARE #Schemaname VARCHAR(50),
#TableName VARCHAR(50),
#FiledName VARCHAR(50)
CREATE TABLE #udtflds
(
Schemaname VARCHAR(50),
TableName VARCHAR(50),
FiledName VARCHAR(50)
)
SELECT TOP 1
#Datatype = Data_type,
#Datasize = character_maximum_length
FROM INFORMATION_SCHEMA.COLUMNS
WHERE Domain_name = #udt
AND Domain_schema = #udtschema
SET #varcharDataType = #Datatype
IF #DataType Like '%char%'
AND #Datasize IS NOT NULL
AND ( #newudtDataType <> 'varchar(max)'
OR #newudtDataType <> 'nvarchar(max)'
)
BEGIN
SET #varcharDataType = #varcharDataType + '('
+ CAST(#Datasize AS VARCHAR(50)) + ')'
END
INSERT INTO #udtflds
SELECT TABLE_SCHEMA,
TABLE_NAME,
Column_Name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE Domain_name = #udt
AND Domain_schema = #udtschema
DECLARE #exec VARCHAR(500)
DECLARE alter_cursor CURSOR
FOR SELECT Schemaname,
TableName,
FiledName
FROM #udtflds
OPEN alter_cursor
FETCH NEXT FROM alter_cursor INTO #Schemaname, #TableName, #FiledName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #exec = 'Alter Table ' + #Schemaname + '.' + #TableName
+ ' ALTER COLUMN ' + #FiledName + ' ' + #varcharDataType
EXECUTE ( #exec
)
FETCH NEXT FROM alter_cursor INTO #Schemaname, #TableName, #FiledName
END
CLOSE alter_cursor
SET #exec = 'DROP TYPE [' + #udtschema + '].[' + #udt + ']'
EXEC ( #exec
)
SET #varcharDataType = #newudtDataType
IF #newudtDataType Like '%char%'
AND #newudtDataSize IS NOT NULL
AND ( #newudtDataType <> 'varchar(max)'
OR #newudtDataType <> 'nvarchar(max)'
)
BEGIN
SET #varcharDataType = #varcharDataType + '('
+ CAST(#newudtDataSize AS VARCHAR(50)) + ')'
END
SET #exec = 'CREATE TYPE [' + #newudtschema + '].[' + #udt + '] FROM '
+ #varcharDataType + ' ' + #OtherParameter
EXEC ( #exec
)
OPEN alter_cursor
FETCH NEXT FROM alter_cursor INTO #Schemaname, #TableName, #FiledName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #exec = 'Alter Table ' + #Schemaname + '.' + #TableName
+ ' ALTER COLUMN ' + #FiledName + ' ' + '[' + #newudtschema
+ '].[' + #udt + ']'
EXECUTE ( #exec
)
FETCH NEXT FROM alter_cursor INTO #Schemaname, #TableName, #FiledName
END
CLOSE alter_cursor
DEALLOCATE alter_cursor
SELECT *
FROM #udtflds
DROP TABLE #udtflds
1: http://www.sql-server-performance.com/2008/how-to-alter-a-uddt/ has replaced http://www.sql-server-performance.com/faq/How_to_alter_a%20_UDDT_p1.aspx
The simplest way to do this is through Visual Studio's object explorer, which is also supported in the Community edition.
Once you have made a connection to SQL server, browse to the type, right click and select View Code, make your changes to the schema of the user defined type and click update. Visual Studio should show you all of the dependencies for that object and generate scripts to update the type and recompile dependencies.
As devio says there is no way to simply edit a UDT if it's in use.
A work-round through SMS that worked for me was to generate a create script and make the appropriate changes; rename the existing UDT; run the create script; recompile the related sprocs and drop the renamed version.
The solutions provided here can only be applied if the user defined types are used in table definitions only, and if the UDT columns are not indexed.
Some developers also have SP's and functions using UDT parameters, which is not covered either. (see comments on Robin's link and in the Connect entry)
The Connect entry from 2007 has finally been closed after 3 years:
Thank you for submitting this
suggestion, but given its priority
relative to the many other items in
our queue, it is unlikely that we will
actually complete it. As such, we are
closing this suggestion as “won’t
fix”.
I tried to solve a similiar problem ALTERing XML SCHEMA COLLECTIONS, and the steps seem to mostly apply to ALTER TYPE, too:
To drop a UDT, the following steps are necessary:
If a table column references the UDT, it has to be converted to the underlying type
If the table column has a default constraint, drop the default constraint
If a procedure or function has UDT parameters, the procedure or function has to be dropped
If there is an index on a UDT column, the index has to be dropped
If the index is a primary key, all foreign keys have to be dropped
If there are computed columns based on a UDT column, the computed columns have to be dropped
If there are indexes on these computed columns, the indexes have to be dropped
If there are schema-bound views, functions, or procedures based on tables containing UDT columns, these objects have to be dropped
I ran into this issue with custom types in stored procedures, and solved it with the script below. I didn't fully understand the scripts above, and I follow the rule of "if you don't know what it does, don't do it".
In a nutshell, I rename the old type, and create a new one with the original type name. Then, I tell SQL Server to refresh its details about each stored procedure using the custom type. You have to do this, as everything is still "compiled" with reference to the old type, even with the rename. In this case, the type I needed to change was "PrizeType". I hope this helps. I'm looking for feedback, too, so I learn :)
Note that you may need to go to Programmability > Types > [Appropriate User Type] and delete the object. I found that DROP TYPE doesn't appear to always drop the type even after using the statement.
/* Rename the UDDT you want to replace to another name */
exec sp_rename 'PrizeType', 'PrizeTypeOld', 'USERDATATYPE';
/* Add the updated UDDT with the new definition */
CREATE TYPE [dbo].[PrizeType] AS TABLE(
[Type] [nvarchar](50) NOT NULL,
[Description] [nvarchar](max) NOT NULL,
[ImageUrl] [varchar](max) NULL
);
/* We need to force stored procedures to refresh with the new type... let's take care of that. */
/* Get a cursor over a list of all the stored procedures that may use this and refresh them */
declare sprocs cursor
local static read_only forward_only
for
select specific_name from information_schema.routines where routine_type = 'PROCEDURE'
declare #sprocName varchar(max)
open sprocs
fetch next from sprocs into #sprocName
while ##fetch_status = 0
begin
print 'Updating ' + #sprocName;
exec sp_refreshsqlmodule #sprocName
fetch next from sprocs into #sprocName
end
close sprocs
deallocate sprocs
/* Drop the old type, now that everything's been re-assigned; must do this last */
drop type PrizeTypeOld;
New answer to an old question:
Visual Studio Database Projects handle the drop and recreate process when you deploy changes. It will drop stored procs that use UDDTs and then recreate them after dropping and recreating the data type.
1.Rename the old UDT,
2.Execute query ,
3.Drop the old UDT.
Simple DROP TYPE first then CREATE TYPE again with corrections/alterations?
There is a simple test to see if it is defined before you drop it ... much like a table, proc or function -- if I wasn't at work I would look what that is?
(I only skimmed above too ... if I read it wrong I apologise in advance! ;)