Linked Server Error - sql-server

I am using Linked server For transferring data using MSDTC
Alter Proc [dbo].[usp_Select_TransferingDatasFromServerCheckingforExample]
#RserverName varchar(100), ----- Server Name
#RUserid Varchar(100), ----- server user id
#RPass Varchar(100), ----- Server Password
#DbName varchar(100) ----- Server database
As
Set nocount on
Set Xact_abort on
Declare #user varchar(100)
Declare #userID varchar(100)
Declare #Db Varchar(100)
Declare #Lserver varchar(100)
Select #Lserver = ##servername
Select #userID = suser_name()
select #User=user
Exec('if exists(Select 1 From [Master].[' + #user + '].[sysservers] where srvname = ''' +
#RserverName + ''') begin Exec sp_droplinkedsrvlogin ''' + #RserverName + ''',''' + #userID +
''' exec sp_dropserver ''' + #RserverName + ''' end ')
declare #ColumnList varchar(max)
set #ColumnList = null
Select #ColumnList = case when #ColumnList is not null then #ColumnList + ',' + quotename(name) else quotename(name) end
From syscolumns where Id = object_id('Crnot') order by colid
Set identity_Insert Crnot On
exec ('Insert Into ['+ #RserverName + '].'+ #DbName + '.'+ #user +'.Crnot ('+ #ColumnList +') Select '+ #ColumnList +' from Crnot ')
Set identity_Insert Crnot Off
Exec sp_droplinkedsrvlogin #RserverName,#userID
Exec sp_dropserver #RserverName
when executing this qry i get the error "No transaction Active"

Check your MS DTC configuration (cut and paste from a doc, not checked recently):
Start, Run, dcomcnfg.exe
In the Component Services window, expand Component Services... Computers...My Computer.
Right-click My Computer, Properties.
Click Security Configuration on the MSDTC tab.
Click to select the Network DTC Access check box.
Set both the Allow Inbound and Allow Outbound check boxes
Under the Transaction Manager Communication group, click to select the No Authentication Required option.
Verify that the DTC Logon Account name is set to NT AUTHORITY\NetworkService.
Click Ok etc
In your code, Set identity_Insert Crnot only applies to local objects.
It should be part of the dynamic SQL INSERT

Related

SQL Server 2016 Change Object Owner

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

Can I use a variable of type varchar with possible dots in SQL Server database?

I'm creating a procedure to add users logins to a specific database. I call this procedure inside a trigger when a user is inserted in my database (I want to have different logins for each user in my site and in the access to the database).
Here's my trigger:
ALTER TRIGGER [dbo].[sys_users_insert]
ON [dbo].[sys_users]
AFTER INSERT
AS
BEGIN
DECLARE #USERNAME varchar(MAX)
SELECT #USERNAME = INSERTED.username
FROM INSERTED
EXEC CreateUser #USERNAME
END
The CreateUser is my procedure to create the logins in the database. The procedure is working. When I call it from a query editor:
EXEC CreateUser 'patricia.santos'
The user is created with success. But when I insert a user in the table and trigger runs the user isn't created nor is inserted in the table. And I found out that if I insert a user without dots in the username everything goes ok. So I believe is something with the dot but I would like to know if there's some workaround to accept usernames with dots.
UPDATE
Here's my procedure for creating logins in my database:
USE mydatabase
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[CreateUser]
#USERNAME AS VARCHAR(MAX) = ''
AS
BEGIN
declare #sql nvarchar(MAX)
If NOT EXISTS(select loginname from master.dbo.syslogins where name = #USERNAME)
BEGIN
set #sql = 'CREATE LOGIN ' + #USERNAME +
' WITH
PASSWORD = ''something'',
CHECK_POLICY = OFF'
exec(#sql)
set #sql = 'ALTER SERVER ROLE sysadmin ADD MEMBER ' + #username
exec(#sql)
IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = #USERNAME)
BEGIN
-- Creates a database user for the login created above.
set #sql = 'CREATE USER [' + #USERNAME + '] FOR LOGIN [' + #USERNAME + ']'
exec(#sql)
EXEC sp_addrolemember 'db_owner', #USERNAME
END
END
END
Thank you :)
I think the issue may be with your CreateUser procedure. Ensure that the “CREATE USER” clause and ALTER SERVER ROLE clause wraps the user name in square brackets. Please see updated procedure below:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[CreateUser]
#USERNAME AS VARCHAR(MAX) = ''
AS
BEGIN
declare #sql nvarchar(MAX)
If NOT EXISTS(select loginname from master.dbo.syslogins where name = #USERNAME)
BEGIN
set #sql = 'CREATE LOGIN [' + #USERNAME + '] ' +
' WITH
PASSWORD = ''something'',
CHECK_POLICY = OFF'
exec(#sql)
set #sql = 'ALTER SERVER ROLE sysadmin ADD MEMBER [' + #username + ']'
exec(#sql)
IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = #USERNAME)
BEGIN
-- Creates a database user for the login created above.
set #sql = 'CREATE USER [' + #USERNAME + '] FOR LOGIN [' + #USERNAME + ']'
exec(#sql)
EXEC sp_addrolemember 'db_owner', #USERNAME
END
END
END
Let me know if this helps at all.

Create Database and user in SQL Server using Oracle SQL Developer IDE

I want to create a new Database in SQL Server using Oracle SQL Developer IDE.
When I am writing a query to create a new DB with user and login details it says user and db is successfully created but I can't see the user in the DB Created.
Below is the command which I am using:
create database subodh_test;
use subodh_test;
CREATE LOGIN test_subodh2
WITH PASSWORD = 'testing';
create user test_subodh2;
Also, Using Microsoft SQL Server Management Studio I am running below command that is executed perfectly:
USE master
DECLARE #DatabaseName sysname
DECLARE #Login sysname
DECLARE #Password sysname
DECLARE #SQLStatement nvarchar(4000)
SET #DatabaseName = N'testing'
SET #Login = N'testing'
SET #Password = N'test123'
SET #SQLStatement = N'ALTER DATABASE ' + #DatabaseName + N' SET
RESTRICTED_USER WITH ROLLBACK IMMEDIATE'
EXEC(#SQLStatement)
SET #SQLStatement = N'DROP DATABASE ' + #DatabaseName
EXEC(#SQLStatement)
EXEC sp_droplogin #Login
SET #SQLStatement = N'CREATE DATABASE ' + #DatabaseName
EXEC(#SQLStatement)
SET #SQLStatement = N'ALTER DATABASE ' + #DatabaseName + ' SET
ANSI_NULL_DEFAULT ON'
EXEC(#SQLStatement)
EXEC sp_addlogin #Login, #Password, #DatabaseName
EXEC sp_addsrvrolemember #Login, 'sysadmin'
SET #SQLStatement = N'USE ' + #DatabaseName +
N' EXEC sp_adduser #Login' +
N' EXEC sp_addrolemember ''db_owner'', #Login'
EXEC sp_executesql #SQLStatement,
N'#Login sysname',
#Login = #Login
Go

How can I quickly delete all databases whose name matches a patttern?

I have many databases that on my SQL Server box that start with a prefix zzz.
Is there a way to do a DROP DATABASE (or some other method) that will remove and delete the data files? If a connection is opened, I want it closed.
Basically I just want them gone.
Generate a drop script, copy/paste & run:
exec master.sys.sp_msforeachdb 'if ''?'' like ''ZZZ%'' print ''drop database [?]'''
Or drop directly in the SQL string if your brave.
use master;
go
-- this will drop all dbs that start with t5....
declare #strsql varchar(500)
declare #curname sysname
select #curname = name from sys.databases
where name like 't5%'
while( ##rowcount> 0)
begin
set #strsql ='ALTER DATABASE ' +#curname +' SET OFFLINE WITH ROLLBACK IMMEDIATE'
exec (#strsql)
set #strsql ='drop database '+#curname
exec (#strsql)
select #curname = name from sys.databases
where name like 't5%'
end
You could write a dynamic SQL to do this:
use master
go
declare #dbnames nvarchar(max)
declare #statement nvarchar(max)
declare #closeconnection nvarchar(max)
set #dbnames = ''
set #statement = ''
select #dbnames = #dbnames + ',[' + name + ']' from sys.databases where name like 'zzz%'
if len(#dbnames) = 0
begin
print 'no databases to drop'
end
else
BEGIN
SET #closeconnection = 'alter database ' + substring(#dbnames, 2, len(#dbnames))
+ ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE'
set #statement = 'drop database ' + substring(#dbnames, 2, len(#dbnames))
print #statement
EXEC sp_executesql #closeconnection;
exec sp_executesql #statement;
end
Normally, the syntax to close all active connections to a database is:
--set it to single user to disable any other connections
ALTER DATABASE YourDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE
--do your stuff here
--set it back to multiple users
ALTER DATABASE YourDatabase SET MULTI_USER
Alternatively, you could also generate a dynamic select list that populates your drop database statement along with close connection statements like this:
USE master;
Go
SELECT 'DROP DATABASE '+ name,
'alter database ' + name + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE'
FROM sys.databases WHERE name like 'zzz%';
GO
Courtesy: #SeriousM and OFH
I modified benjamin's script a bit so you only have to declare the prefix once.
use master;
declare #dbPrefix varchar(10)
set #dbPrefix = 'zzz_%';
declare #strsql varchar(500)
declare #curname sysname
select #curname = name from sys.databases
where name like #dbPrefix
while( ##rowcount> 0)
begin
set #strsql ='ALTER DATABASE ' +#curname +' SET SINGLE_USER WITH ROLLBACK IMMEDIATE'
exec (#strsql)
set #strsql ='drop database '+#curname
exec (#strsql)
select #curname = name from sys.databases
where name like #dbPrefix
end

how to delete only Windows Login in SQL Server

I am using below code to delete SQL Logins
declare #name varchar(1000)
declare #xtype varchar(20)
declare #sqlstring nvarchar(4000)
declare SPViews_cursor cursor for
SELECT QUOTENAME(NAME) AS name
FROM sys.server_principals
open SPViews_cursor
fetch next from SPViews_cursor into #name
while ##fetch_status = 0
begin
set #sqlstring = 'drop LOGIN ' + #name
exec sp_executesql #sqlstring
set #sqlstring = ' '
fetch next from SPViews_cursor into #name
end
close SPViews_cursor
deallocate SPViews_cursor
but it is dropping all logins, I just need to drop Windows login so only SQL auth. can be possible. Any suggestion? And can this code be made shorter?
Change your query to this:
SELECT QUOTENAME(NAME) AS name
FROM sys.server_principals
WHERE type = 'U'
U means Window Login. You can find more info here.
USE type_desc or type column to filter 'Windows Login'
SELECT QUOTENAME(NAME) AS name
FROM sys.server_principals
where type_desc = 'WINDOWS_LOGIN'

Resources