I Edited my question so it can be clearer,
In sys.server there is a row that called server_id,
I wanted to know if there is any name to get the database name from this server id,
I am working with replication and linked server so i wanted to make a query that takes all the server and get database names,
I dont need all the database that on the server.
Thank you for your help.
Taking your edit into consideration and removing my previous answer, I don't have an exact answer, but some additional metadata that might help: sys.linked_logins, sp_linkedservers.
Perhaps you could just get each linked server name and use OPENQUERY to query the sys.databases catalog on the remote server?
-- this would be done in some kind of loop:
DECLARE #linkedSvrName sysname = (SELECT TOP 1 name FROM sys.servers WHERE server_id > 0);
DECLARE #sql nvarchar(4000) = 'SELECT * FROM OPENQUERY(' + #linkedSvrName + ', ''SELECT name FROM sys.databases'')';
EXEC sys.sp_executesql #sql
(I didn't have any linked server entries to test against to see if this would actually work as expected.)
Related
I have a SQL 2008 database that is stored on the same instance, but this database is created by the user and name is stored in SQL table. How do I write a select statement using dynamic sql or is there a another way
So for example:
Main database - myDB
User database - userDB (this is stored in a myDB.dbo.tblUserDatabase)
userDB has a table called tblUserReports
I want to write something like this in dynamic sql:
SELECT * FROM userDB.dbo.tblUserReports
So tried:
declare #dbUser varchar(50)
set #dbUser = (SELECT strDBName FROM myDB.dbo.tblUserDatabase)
SELECT * FROM #dbUser.dbo.tblUserReports
You can do this... dynamic sql can become unmanageable very quickly so be careful.
declare #dbUser varchar(50)
set #dbUser = (SELECT strDBName FROM myDB.dbo.tblUserDatabase)
DECLARE #sql NVARCHAR(1000)
SET #sql = 'SELECT * FROM ' + QUOTENAME(#dbUser) + '.dbo.tblUserReports'
EXEC sp_executesql #sql
You cannot parameterise the table name. You will have to use dynamic SQL in your client or stored procedures. It's a very unusual thing to want to do so think long & hard about if this is a good design. Maybe if you share what you are doing then you'll get some additional ideas as to how to approach your problem.
I would like to split my database into two databases, a quick check showed that I can easily query, join, update tables across databases.
My main problem now is that to do this, I will have to do something like this.
SELECT *
FROM Database1.dbo.Table1,
Database2.dbo.Table2
As you can see I have to explicit mentioned database names, which means that if database name is deployed with a different name, this code will not work anymore.
Any ideas to overcome this problem?
You can use db_name() to get the current database name and dynamic sql to build a dynamic query.
Something like:
declare #databaseName nvarchar(max) = db_name()
declare #dynamicSql nvarchar(max) = 'SELECT * FROM '+ #databaseName + '.dbo.Table1'
exec sp_executesql #dynamicSql
I restored a database after a server failure and now I'm running into a problem where the table names show as database_user_name.table_name. So when I query something like:
select * from contacts
it doesn't work because it expects it be fully qualified, as in:
select * from user1000.contacts
The problem with this is that I have hundreds of stored procedures that reference the tables with their name, so none of the queries work.
Is there a way to tell SQL Server 2005 to drop the username from the table without changing the user as the owner?
try this advice from the manual:
To change the schema of a table or view by using SQL Server Management Studio, in Object Explorer, right-click the table or view and then click Design. Press F4 to open the Properties window. In the Schema box, select a new schema.
If you are sure none of the tables exist in the dbo schema as well, then you can say:
ALTER SCHEMA dbo TRANSFER user1000.contacts;
To generate a set of scripts for all of the tables in that schema, you can say:
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'
ALTER SCHEMA dbo TRANSFER user1000.' + QUOTENAME(name) + ';'
FROM sys.tables
WHERE SCHEMA_NAME([schema_id]) = N'user1000';
PRINT #sql;
--EXEC sp_executesql #sql;
(Once you're happy with the PRINT output - acknowledging that it will be truncated at 8K even though the variable really contains the whole script - uncomment the EXEC and run it again. This does not check for potential conflicts.)
But the real fix is to fix your code. You should never say select * from contacts - both the * and the missing schema prefix can be problematic for various reasons.
I have one instance of SSMS open and I am connected to one remote server as well as localhost. How can I get the names of all the servers that SSMS is currently connected to? The emblem of the remote server looks like
and the local looks like
Also, I would like to know if there's any problems with connecting to multiple servers from one instance of SSMS, and how to switch between servers through a script without clicking on a table name and doing something like select top 1000 rows
Okay there are multiple issues at work here as this is not always a simple answer. Depending on your environment and rights you may have one or more many permission groups that have access to one or many environments which have one or many servers that thus have access to one or many databases. However if you do have permission and you have linked servers set up with data access you can do something like this to get a listing of things you have access to. You could run this similarly on different environments making it into a procedure that you could call with ADO.NET or similar.
--declare variable for dynamic SQL
DECLARE
#SQL NVARCHAR(512)
, #x int
-- Create temp table to catch linked servers
Declare #Servers TABLE
(
Id int identity
, ServerName VARCHAR(128)
)
-- insert linked servers
insert into #Servers
select name
FROM sys.servers
-- remove temp table if it exists as it should not be prepopulated.
IF object_ID('tempdb..#Databases') IS NOT NULL
DROP TABLE tempdb..#Databases
;
-- Create temp table to catch built in sql stored procedure
CREATE TABLE #Databases --DECLARE #Procs table
(
ServerName varchar(64)
, DatabaseName VARCHAR(128)
)
SET #X = 1
-- Loops through the linked servers with matching criteria to examine how MANY there are. Do a while loop while they exist.
WHILE #X <= (SELECT count(*) FROM #Servers)
BEGIN
declare #DB varchar(128);
Select #DB = ServerName from #Servers where Id = #X -- get DB name from current cursor increment
-- Set up dynamic SQL but do not include master and other meta databases as no one cares about them.
SET #SQL = 'insert into #Databases select ''' + #Db + ''', name from ' + #DB + '.master.sys.databases
where name not in (''master'',''tempdb'',''model'',''msdb'')'
-- Execute the dynamic sql to insert into collection object
exec sp_executesql #SQL
-- increment for next iteration on next server
SET #X = #X + 1
END
;
SELECT *
FROM #Databases
I'm not entirely sure what you are asking. If you are asking if you can connect to multiple instances of SQL Server in a single query window the answer is yes. I went into detail on how and some of the implications here: Multiple instances, single query window
If on the other hand you are asking how to tell what instance you are connected to you can use ##SERVERNAME.
SELECT ##SERVERNAME
It will return the name of the instance you are connected to.
Typically you would connect to one instance per query window and flip between the windows to affect the specific instance you are interested in.
If you want to write a command to send you to a specific instance you can set your query window to SQLCMD mode (Query menu -> SQLCMD Mode) and use the :CONNECT command.
:CONNECT InstaneName
SELECT ##SERVERNAME
I'm looking to query all databases mapped to a user, similar to Security > Logins > Properties > User Mapping.
This may be done in SQL 2005 if possible
For example, something similar to:
SELECT name
FROM sys.databases
WHERE HAS_DBACCESS(name) = 1
But perform the query from an administrative user, as opposed to running the above query as the user itself.
How would something like this be performed?
Thank you.
Well this might be a start, probably not the nice output you'd hope for (and it produces two resultsets):
EXEC sp_helplogins N'floob';
But it does work on SQL Server 2000. If you want to try and replicate some of the functionality in the procedure, you can see how it's checking for permissions, basically a cursor through every database. On SQL Server 2000:
EXEC sp_helptext N'sp_helplogins';
On 2005+ I much prefer the output of OBJECT_DEFINITION():
SELECT OBJECT_DEFINITION(OBJECT_ID(N'sys.sp_helplogins'));
So you could write your own cursor based on similar logic, and make the output prettier...
Here is a quick (and not complete) example, doesn't cover much but an idea to get started if the above is not sufficient:
DECLARE #login NVARCHAR(255);
SET #login = N'foobarblat';
-- above would be an input parameter to a procedure, I presume
CREATE TABLE #dbs(name SYSNAME);
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'INSERT #dbs SELECT ''' + name + ''' FROM '
+ QUOTENAME(name) + '.sys.database_principals AS u
INNER JOIN sys.server_principals AS l
ON u.sid = l.sid
WHERE l.name = #login;'
FROM sys.databases
WHERE state_desc = 'ONLINE'
AND user_access_desc = 'MULTI_USER';
EXEC sp_executesql #sql, N'#login SYSNAME', #login;
SELECT name FROM #dbs;
DROP TABLE #dbs;
As I said, this is not complete. Won't know if the user has been denied connect, is member of deny reader/writer roles, won't show the alias if the user name in the db doesn't match the login, etc. You can dig into more details from sp_helplogins depending on what you want to show.
The EXECUTE AS functionality was added in the 2005 release, so I don't think you can run that in 2000. You could probably mimick it by putting the relevant code in a job and setting the job owner to an admin user, but it would process with the job not inline.