How to query the name of the current SQL Server database instance? - sql

It is a bit of a "chicken or egg" kind of query, but can someone dreamup a query that can return the name of the current database instance in which the query executes? Believe me when I say I understand the paradox: why do you need to know the name of the database instance if you're already connected to execute the query? Auditing in a multi-database environment.
I've looked at all the ## globals in Books Online. "SELECT ##servername" comes close, but I want the name of the database instance rather than the server.

SELECT DB_NAME()
Returns the database name.

SELECT
##servername AS 'Server Name' -- The database server's machine name
,##servicename AS 'Instance Name' -- e.g.: MSSQLSERVER
,DB_NAME() AS 'Database Name'
,HOST_NAME() AS 'Host Name' -- The database client's machine name

I'm not sure what you were exactly asking. As you are writing this procedure for an Auditing need I guess you're asking how do you get the current database name when the Stored Procedure exists in another database. e.g.
USE DATABASE1
GO
CREATE PROC spGetContext AS
SELECT DB_NAME()
GO
USE DATABASE2
GO
EXEC DATABASE1..spGetContext
/* RETURNS 'DATABASE1' not 'DATABASE2' */
This is the correct behaviour, but not always what you're looking for. To get round this you need to create the SP in the Master database and mark the procedure as a System Procedure. The method of doing this differs between SQL Server versions but here's the method for SQL Server 2005 (it is possible to do in 2000 with the master.dbo.sp_MS_upd_sysobj_category function).
USE MASTER
/* You must begin function name with sp_ */
CREATE FUNCTION sp_GetContext
AS
SELECT DB_NAME()
GO
EXEC sys.sp_MS_marksystemobject sp_GetContext
USE DATABASE2
/* Note - no need to reference master when calling SP */
EXEC sp_GetContext
/* RETURNS 'DATABASE2' */
Hope this is what you were looking for

You can use DB_NAME() :
SELECT DB_NAME()

SELECT DB_NAME() AS DatabaseName

simply use:
select ##servicename

You should be able to use:
SELECT SERVERPROPERTY ('InstanceName')

You can get the instance name of your current database as shown below:
SELECT ##SERVICENAME -- SQLEXPRESS
SELECT SERVERPROPERTY ('InstanceName') -- SQLEXPRESS

Related

SQL create database if not exists, unexpected behaviour

I have a long stored procedure which begins with the following statement:
IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = N'DBNAME')
BEGIN
CREATE DATABASE [DBNAME]
END;
It is expected to create the DB on my local server, if it does not exist. The problem is that almost all of the time it goes thorugh this part of the stored procedure and does not create it, which then interferes with the other code from the same procedure. On the other hand, in very rare cases, it creates the DB. My question is: Is there a better way to check if the DB exists, because I have already tried at least 10.
Other ways I tried:
IF NOT EXISTS (SELECT 1 FROM sys.databases WHERE name = N'DBNAME')
BEGIN
CREATE DATABASE [DBNAME]
END;
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'DBNAME')
BEGIN
CREATE DATABASE [DBNAME]
END;
IF NOT EXISTS (SELECT name FROM master.dbo.sys.databases WHERE name = N'DBNAME')
BEGIN
CREATE DATABASE [DBNAME]
END;
But if I run it outside of my sp, it works perfectly, which makes me think that it can be some problem related to permissions.
Try using
If(db_id(N'DBNAME') IS NULL)
If that does not work, it could be the permissions. That would explain why you are not getting an error message.
...minimum permissions required to see the corresponding row are
ALTER ANY DATABASE or VIEW ANY DATABASE server-level permission, or
CREATE DATABASE permission in the master database. The database to
which the caller is connected can always be viewed in sys.databases
(From sys.databases on MS documentation)
What permissions does the user under which you are running has?
Try changing your code to just return the contents of sys.databases so you can see it.
The issue appears to be a lack of 'GO' to terminate the statements. This does not work...
IF NOT EXISTS(SELECT 1 FROM sys.databases WHERE name='dba')
CREATE DATABASE [dba]
USE [dba]
But, this does...
IF NOT EXISTS(SELECT 1 FROM sys.databases WHERE name='dba')
CREATE DATABASE [dba]
GO
USE [dba]
Troy.
#
Chiming in because I had a similar issue: I wanted to create a database if it does not exist, then perform operations on that database.
I think the problem was that the script tried to run in one batch, so it tried to USE the database before the SQL server received the CREATE command.
This resulted in the whole script getting reverted and it seemed like the root of the issue was that the database never got created.
In my case the solution was to add a GO command after the initial part of the script where the table gets created but before I start working with it (e.g. creating tables).
When comparing strings use LIKE
if (SELECT count(name) FROM sys.databases WHERE name LIKE '%DBNAME%') = 0

Find out current database name (MSSQL)

If I want to know the server I can use:
##SERVERNAME
Is there an equivalent function for getting database/catalog name.
I know that we can set it in the script with USE statement but what if it wasnt set and I wanted to query within a sproc what db I was using.
db_name() will give you the name of the current database.
This should do it:
SELECT DB_NAME() AS DataBaseName
Per SQL Authority
db_name() will get you the name of database that you using.
you can see the result with:
select db_name()
With the MSSQL queries below, you can check the current database:
SELECT DB_NAME()
GO
master
In addition, if you don't specify a database on sqlcmd, "master" database is used by default.

How to determine if database exists on linked server?

I know you can do something like:
select count(*) as Qty from sys.databases where name like '%mydatabase%'
but how could you do something like:
select count(*) as Qty from linkedServer.sys.databases where name like '%mydatabases%'
I guess I could put a stored procedure on the linked server and execute the first select, but is there a way to query a linked server for what databases it holds?
Assuming your linked server login has read permissions on the master.sys.databases table, you can use the following:
select * from linkedserver.master.sys.databases
In the past, I've used this very query on SQL Server 2008 R2.
I think its just a matter of your syntax that is stopping you, try using single quotes instead of %% around your database name:
SELECT COUNT(*) as Qty FROM LinkedServer.master.sys.databases where name like 'mydatabase'
The correct formatting for selecting a Linked Server has already been answered here:
SQL Server Linked Server Example Query
Listed below is a link to a cursor that works:
http://jasonbrimhall.info/2012/03/05/are-my-linked-servers-being-used/
The query will need some rework to include all functions and triggers though.
I'm not sure if a remote master DB is always available through a linked server.
I'll be using the following TRY CATCH probe
BEGIN TRY
EXEC ('SELECT TOP 1 1 FROM MyLinkedServer.MyTestDb.INFORMATION_SCHEMA.TABLES')
END TRY
BEGIN CATCH
PRINT 'No MyTestDB on MyLinkedServer'
END CATCH

How to pass database name into stored procedure?

How to pass database name into stored procedure? I tried something like
create procedure dbo.Test
#databaseName varchar(100)
as
select * from #databasename.Person.Address
go
I would like to use it like this
execute dbo.Test #databaseName = 'AdventureWorks'
This is not possible in the manner you are describing.
You can do this with dynamic SQL, but that brings its own set of problems.
Sounds like you are trying to move information which should be part of connection string into stored procedure logic. If you expect that Person table will be in different database this database name should be fixed in deployment - for example by parametrized creation script and sqlcmd.

SQL - How to insert results of Stored_Proc into a new table without specifying columns of new table?

Using SQL Server 2005, I'd like to run a stored procedure and insert all of the results into a new table.
I'd like the new table to have its columns automatically configured based upon the data returned by the stored procedure.
I am familiar with using the SELECT ... INTO syntax:
SELECT * INTO newtable FROM oldtable
Is this possible?
Edit for clarification: I'm hoping to accomplish something like:
Select * INTO newtable FROM exec My_SP
The only way to do this is w/ OPENROWSET against the local server:
SELECT * INTO #temp
FROM OPENROWSET (
'SQLOLEDB'
, 'Server=(local);TRUSTED_CONNECTION=YES;'
, 'SET FMTONLY OFF EXEC database.schema.procname'
) a
But this is kind of a last-ditch-gotta-do-it-damn-the-consequences kind of method. It requires elevated permissions, won't work for all procedures, and is generally inefficient.
More info and some alternatives here: http://www.sommarskog.se/share_data.html
This seems like a horrible design. You're really going to create a new table to store the results of a stored procedure, every time the stored procedure is called? And you really can't create the table in advance because you have absolutely no idea what kind of output the stored procedure has? What if the stored procedure returns multiple resultsets? What if it has side effects?
Okay, well, if that's what you really want to do...
One way to accomplish this is to use your local server as a linked server and utilize OPENQUERY. First you need to make sure your local server is configured for data access:
EXEC sp_serveroption 'local server name', 'DATA ACCESS', true;
Then you can do something like this:
SELECT * INTO dbo.newtable
FROM OPENQUERY('local server name', 'EXEC yourdb.dbo.yourproc;');
PS How are you going to write code that is going to perform SELECT INTO into a new table name every time (because you can only do SELECT INTO once)? Dynamic SQL? What happens if two users run this code at the same time? Does one of them win, and the other one just gets an error message?
A variation of the same is
create table somename
select * from wherever;