In SQL Server, I have a database abc. In this database I have hundreds of tables. Each of these tables is called xyz.table
I want to change all the tables to be called abc.table.
Do we have a way by which I can change all the names from xyz.table to abc.table in database abc?
I am able to manually change the name by changing the schema for each table to abc
You could have a cursor run over all your tables in the xyz schema and move all of those into the abc schema:
DECLARE TableCursor CURSOR FAST_FORWARD
FOR
-- get the table names for all tables in the 'xyz' schema
SELECT t.Name
FROM sys.tables t
WHERE schema_id = SCHEMA_ID('xyz')
DECLARE #TableName sysname
OPEN TableCursor
FETCH NEXT FROM TableCursor INTO #TableName
-- iterate over all tables found
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #Stmt NVARCHAR(999)
-- construct T-SQL statement to move table to 'abc' schema
SET #Stmt = 'ALTER SCHEMA abc TRANSFER xyz.' + #TableName
EXEC (#Stmt)
FETCH NEXT FROM TableCursor INTO #TableName
END
CLOSE TableCursor
DEALLOCATE TableCursor
You can use Alter Schema with an undocumented Stored Procedure exec sp_MSforeachtable which basically iterates through all the tables .
exec sp_MSforeachtable "ALTER SCHEMA new_schema TRANSFER ? PRINT '? modified' "
change the new_schema keyword with your new Schema .
For details please go through the link
sp_MSforeachtable
Alter Schema for all the tables
As others have pointed out that the SP is deprecated so There is another way to do this by getting the names of the table from sys.tables
Declare #value int
Set #value=1
declare #sql varchar(max), #table varchar(50), #old varchar(50), #new varchar(50)
set #old = 'dbo'
set #new = 'abc'
while exists(select * from sys.tables where schema_name(schema_id) = #old)
begin
;With CTE as
(
Select *,row_number() over(order by object_id) rowNumber from sys.tables
where schema_name(schema_id) = #old
)
select #table= name from CTE where #value=rowNumber
Set #value=#value+1
set #sql = 'alter schema ' + #new + ' transfer ' + #old + '.' + #table
exec(#sql)
end
I'm assuming You've already created the schema abc in the database.
If not you can refer here
http://www.youtube.com/watch?v=_DDgv8uek6M
http://www.quackit.com/sql_server/sql_server_2008/tutorial/sql_server_database_schemas.cfm
To change the schema of all the tables in database you can use following system created msforeachtable stored procedure to rename schema of each table with alter schema.
exec sp_MSforeachtable "ALTER SCHEMA abc TRANSFER ? PRINT '? modified' "
Without using the undocumented/unsupported sp_MSforeachtable procedure, here's a somewhat concise way to select and/or run all of the necessary ALTER statements for every table on the given schema:
declare #oldSchema nvarchar(50) = 'abc' -- usually 'dbo'
declare #newSchema nvarchar(50) = 'xyz' -- use your new schema name
declare #sql nvarchar(max) =
(select
(select N'alter schema [' + #newSchema + '] transfer [' + #oldSchema + '].[' + name + ']
' as 'data()'
from sys.tables
where schema_name(schema_id) = #oldSchema for xml path(''), type)
.value('text()[1]','nvarchar(max)'))
-- You can select out the results for scrutiny
select #sql
-- Or you can execute the results directly
exec (#sql)
This avoids using a cursor, and uses brackets to escape table names that may conflict with SQL keywords.
Related
I've inherited a SQL 2008 dbase in which all of its objects are prefixed with the name of the developer as owner, i.e. ownername.sp_get_all_users.
I've restored the dbase onto SQL Server 2016 Express Edition.
There are several hundred dbase objects, is there a way to automate changing the object owners to dbo rather than manually editing each object?
I've tried the following but apparently you can no longer make ad-hoc changes to objects since SQL Server 2005?
SELECT * from sysobjects where uid = user_id('UseNAme')
declare #Return int
exec #Return = sp_configure 'allow updates', '1'
SELECT #Return as 'Returned Code'
GO
reconfigure WITH OVERRIDE
GO
DECLARE #Rows int, #Error int
BEGIN TRANSACTION
update sysobjects set uid = user_id('dbo') where uid = user_id('UseNAme')
SELECT #Error = ##Error, #Rows = ##RowCount
SELECT #Rows as '#Rows'
IF #Rows > 0
BEGIN
SELECT #Rows AS '#Rows'
COMMIT TRANSACTION
END
else
BEGIN
SELECT #Error AS 'Error #'
ROLLBACK TRANSACTION
END
exec sp_configure 'allow updates', '0'
reconfigure WITH OVERRIDE
go
Any help most appreciated.
You have to use Alter Schema...
ALTER SCHEMA oldschemaname TRANSFER dbo.Address;
To Automate use below
this will change all tables which have a schema other than system to dbo,note if you have two tables in different schema,they can't exist in same schema
select *,row_number() over (order by (select null)) as rownum
into #tables
from information_Schema.tables
where table_schema in (select name from sys.schemas
where name not in ('dbo','guest','INFORMATION_SCHEMA','sys') and principal_id <16384
)
now move
declare #min int,#max int
select #min=min(rownum),#max=max(rownum)
from #tables
declare #tblname varchar(255),#schemaname sysname
declare #sql varchar(max)
while #min<=#max
Begin
select #tblname=table_name,#schemaname=table_schema from
#tables where rownum=#min
set #sql='alter schema dbo transfer '+ #schemaname+'.'+#tblname
--print #sql
exec(#sql)
Set #min=#min+1
End
sp_change object owner as per documentation states..
This stored procedure only works with the objects available in MicrosoftSQL Server 2000. This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature. Use ALTER SCHEMA or ALTER AUTHORIZATION instead. sp_changeobjectowner changes both the schema and the owner. To preserve compatibility with earlier versions of SQL Server, this stored procedure will only change object owners when both the current owner and the new owner own schemas that have the same name as their database user names.
Use this sp_changeobjectowner
As explained here MSDN
For example: EXEC sp_changeobjectowner 'YourObject', 'dbo'
You can use this to alter schema statement for newer SQL Server DBS
declare #sql varchar(8000), #table varchar(1000), #oldschema varchar(1000), #newschema varchar(1000)
set #oldschema = 'dbo'
set #newschema = 'exe'
while exists(select * from sys.tables where schema_name(schema_id) = #oldschema)
begin
select #table = name from sys.tables
where object_id in(select min(object_id) from sys.tables where schema_name(schema_id) = #oldschema)
set #sql = 'alter schema ' + #newschema + ' transfer ' + #oldschema + '.' + #table
exec(#sql)
end
Your general idea of looping through the objects owned by the developer is a good idea (assuming you've tested the heck out of it). I'd suggest using the ALTER AUTHORIZATION command instead MSDN Doc
In addition to the advice above, the following changes the owner of SPs:
Declare #sql varchar(8000),
#table varchar(1000),
#oldschema varchar(1000),
#newschema varchar(1000)
set #oldschema = 'developername'
set #newschema = 'dbo'
while exists(select * from information_schema.routines where routine_type = 'PROCEDURE' and routine_schema = #oldschema )
begin
select #table = SPECIFIC_NAME from information_schema.routines
where SPECIFIC_NAME in(select SPECIFIC_NAME from information_schema.routines where routine_type = 'PROCEDURE' and routine_schema = #oldschema)
set #sql = 'alter schema ' + #newschema + ' transfer ' + #oldschema + '.' + #table
exec(#sql)
end
I am doing work for a company that stores each of their client's info in a different database. When a table needs modification, I have to go to each database and run the ALTER TABLE script. Is there a way I can use a prepared statement to run through all 100+ DBO names?
ALTER TABLE ?.dbo.profileTable
ADD COLUMN profileStatus int
where ? = 'CompanyA, CompanyB, CompanyC' or something similar?
Use Sp_MSforeachdb
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; alter query'
[?] is used as a placeholder for the heretofore unspecified database name
You can modify the query as per your needs ,to exclude system databases use like below..
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; IF DB_ID(''?'') > 4 begin yourquery end'
This will exclude any database that does not have the table you are looking for including system databases.
Declare #TableName Varchar(8000) = 'ProfileTable'
Declare #Sql Varchar(8000)
Select #Sql = Stuff(
(Select ';', 'Alter Table ' + Name + SqlText
From sys.databases
Cross Apply (Select '.dbo.profileTable ADD profileStatus int' SqlText) CA
Where Case When State_Desc = 'ONLINE'
Then Object_Id (QuoteName(Name) + '.[dbo].' + #TableName, 'U')
End Is Not Null
FOR XML PATH('')
),1,1,'')
Exec (#Sql)
This ? before is database ([database].[schema].[table]). Thus you can use sp_MSforeachdb or, as I prefer, use sys.databases view to prepare dynamic queries.
Beware, both methods can interfere with system databases.
Take a look at this solution:
DECLARE #query nvarchar(MAX)='';
SELECT #query = #query + 'USE '+QUOTENAME(name)+';ALTER TABLE dbo.profileTable ADD profileStatus int;'
FROM sys.databases
WHERE OBJECT_ID(QUOTENAME(name)+'.dbo.profileTable', 'U') IS NOT NULL
EXEC(#query)
It adds column col1 int to each dbo.profileTable in every database.
I would like to use variables instead of schema name in at create time for tables or views.
Eg instead of
create table dbo.TableName
I want to
create table #schema.TableName
Also I would like to write below statement with the mentioned solution.
IF OBJECT_ID (N'dbo.TableName', 'u') IS NOT NULL
DROP table TableName;
go
Is this way totally possible or not, if it's possible which way is more efficient.
You can build your statement concatenating objects names and use sp_executesql to submit it to the server:
Using sp_executesql
For example, creating:
DECLARE #SQLString NVARCHAR(500);
DECLARE #TableName NVARCHAR(100);
SET #TableName = 'dbo.TableName';
SET #SQLString = 'CREATE TABLE ' + #TableName + ' ...';
EXECUTE sp_executesql #SQLString;
and dropping:
SET #TableName = 'dbo.TableName';
SET #SQLString = 'IF OBJECT_ID (''' + #TableName + ''', ''u'') IS NOT NULL DROP table ' + #TableName;
EXECUTE sp_executesql #SQLString;
You'll have to mitigate the "Sql Injection" risk if you are getting the object names from the user.
You need to research "sqlcmd" mode.
http://msdn.microsoft.com/en-us/library/ms174187.aspx
Example. Note, in SSMS, Under "Query" there is a "SqlCmd Mode" menu item you need to enable.
:setvar MySchemaName "dbo"
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'$(MySchemaName)' and TABLE_NAME = N'Ticket' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [$(MySchemaName)].[Ticket]
END
GO
CREATE TABLE [$(MySchemaName)].[Ticket] (
[TicketUUID] [uniqueidentifier] NOT NULL,
[CreateDate] [datetime] NOT NULL DEFAULT CURRENT_TIMESTAMP
)
GO
SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'$(MySchemaName)' and TABLE_NAME = N'Ticket' and TABLE_TYPE = N'BASE TABLE'
I am trying to see a list of tables from Adventureworks DB from "Person" schema in Sql Server 2008. I developed the following SP, but after running it as follows it gives me error "Incorrect syntax near ')'". Do you know how I can revise this SP or exec statement?
CREATE PROCEDURE [getTableNames]
#SchemaName VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
SET #SchemaName = 'PERSON'
DECLARE #cmd AS VARCHAR(max)
SET #SchemaName = RTRIM(#SchemaName)
SET #cmd = N'SELECT TABLE_NAME ' +
'FROM information_schema.Tables ' +
'WHERE TABLE_TYPE = ''BASE TABLE'' AND TABLE_SCHEMA = #SchemaName'
END
exec sp_executesql getTableNames, N'#SchemaName NVARCHAR(50), #SchemaName'
You don't actually need to use dynamic SQL here, plus your sproc isn't quite right as you're not executing the #cmd statement. Just use:
CREATE PROCEDURE [getTableNames]
#SchemaName VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON
SELECT TABLE_NAME
FROM information_schema.Tables
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = #SchemaName
END
EXECUTE getTableNames 'PERSON'
You don't need dynamic SQL:
select * from sys.tables
where type_desc = 'BASE TABLE' and schema_id = schema_id(#SchemaName)
I have a table that got into the "db_owner" schema, and I need it in the "dbo" schema.
Is there a script or command to run to switch it over?
In SQL Server Management Studio:
Right click the table and select modify (it's called "Design" now)
On the properties panel choose the correct owning schema.
ALTER SCHEMA [NewSchema] TRANSFER [OldSchema].[Table1]
Show all TABLE_SCHEMA by this select:
SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
You can use this query to change all schema for all tables to dbo table schema:
DECLARE cursore CURSOR FOR
SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA <> 'dbo'
DECLARE #schema sysname,
#tab sysname,
#sql varchar(500)
OPEN cursore
FETCH NEXT FROM cursore INTO #schema, #tab
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'ALTER SCHEMA dbo TRANSFER ' + #schema + '.' + #tab
PRINT #sql
FETCH NEXT FROM cursore INTO #schema, #tab
END
CLOSE cursore
DEALLOCATE cursore
simple answer
sp_changeobjectowner [ #objname = ] 'object' , [ #newowner = ] 'owner'
you don't need to stop all connections to the database, this can be done on the fly.
A slight improvement to sAeid's excellent answer...
I added an exec to have this code self-execute, and I added a union at the top so that I could change the schema of both tables AND stored procedures:
DECLARE cursore CURSOR FOR
select specific_schema as 'schema', specific_name AS 'name'
FROM INFORMATION_SCHEMA.routines
WHERE specific_schema <> 'dbo'
UNION ALL
SELECT TABLE_SCHEMA AS 'schema', TABLE_NAME AS 'name'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA <> 'dbo'
DECLARE #schema sysname,
#tab sysname,
#sql varchar(500)
OPEN cursore
FETCH NEXT FROM cursore INTO #schema, #tab
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'ALTER SCHEMA dbo TRANSFER [' + #schema + '].[' + #tab +']'
PRINT #sql
exec (#sql)
FETCH NEXT FROM cursore INTO #schema, #tab
END
CLOSE cursore
DEALLOCATE cursore
I too had to restore a dbdump, and found that the schema wasn't dbo - I spent hours trying to get Sql Server management studio or visual studio data transfers to alter the destination schema... I ended up just running this against the restored dump on the new server to get things the way I wanted.
When I use SQL Management Studio I do not get the 'Modify' option, only 'Design' or 'Edit'. If you have Visual Studio (I have checked VS.NET 2003, 2005 & 2008) you can use the Server Explorer to change the schema. Right click on the table and select 'Design Table' (2008) or 'Open Table Definition' (2003, 2005). Highlight the complete "Column Name" column. You can then right click and select 'Property Pages' or Properties (2008). From the property sheet you should see the 'Owner' (2003 & 2005) or 'Schema' (2008) with a drop down list for possible schemas.
I use this for situations where a bunch of tables need to be in a different schema, in this case the dbo schema.
declare #sql varchar(8000)
;
select
#sql = coalesce( #sql, ';', '') + 'alter schema dbo transfer [' + s.name + '].[' + t.name + '];'
from
sys.tables t
inner join
sys.schemas s on t.[schema_id] = s.[schema_id]
where
s.name <> 'dbo'
;
exec( #sql )
;
You need to firstly stop all connections to the database, change the ownership of the tables that are 'db_owner' by running the command
sp_MSforeachtable #command1="sp_changeobjectowner ""?"",'dbo'"
where ? is the table name.