MS SQL bulk user and database creation - sql

I'm exploring options to setup a SQL 2016 database server to support teaching students database fundamentals. There will be close to 200 students on the course.
I'd like to automate the creation of all the user accounts and associated database via a script - this means the database for each user needs to be created at the same time. Basically each student's user login name and database will be named as the student's ID. Login authentication will be SQL authentication, not Windows as the lab PCs are not on AD.
If anyone could point me in the direction of any scripts I could modify or use it would be extremely helpful - basically if I go down this route I'll need to do it every year so scripting would be optimal.
Thanks
D.

Using Dynamic Sql and using while loop we can loop the student names and create database and logins.Hope it helps you
IF OBJECT_ID('Tempdb..#USerTable') IS NOT NULL
DROP TABLE #USerTable
IF OBJECT_ID('Tempdb..#USerNameINSERT') IS NOT NULL
DROP TABLE #USerNameINSERT
IF OBJECT_ID('Tempdb..#PasswordsINSERT') IS NOT NULL
DROP TABLE #PasswordsINSERT
--ADD Your student Names Passwords in a single line as below
DECLARE #Usernames NVARCHAR(max) = 'Stud1,Stud2,Stud3,Stud4'
,#Password NVARCHAR(max) = 'Password1,Password2,Password3,Password4'
,#Usernameselect NVARCHAR(max)
,#DatabaseNameselect NVARCHAR(max)
,#PasswordSelect NVARCHAR(max)
,#Usernameselect1 NVARCHAR(max)
,#DatabaseNameselect1 NVARCHAR(max)
,#PasswordSelect1 NVARCHAR(max)
DECLARE #USerName TABLE (
ID INT IDENTITY
,Usernames NVARCHAR(max)
,Passwords NVARCHAR(max)
)
INSERT INTO #USerName (
UserNAmes
,Passwords
)
SELECT #Usernames
,#Password
SELECT ID,UserNAmes INTO #USerNameINSERT
FRom (
SELECT Row_number()Over(Order by (SELECT NULL)) AS ID,Split.a.value('.', 'VARCHAR(1000)') AS UserNAmes
FROM (
SELECT ID, CAST('<S>' + REPLACE(UserNAmes, ',', '</S><S>') + '</S>' AS XML) AS UserNAmes
FROM #USerName
) AS A
CROSS APPLY UserNAmes.nodes('/S') AS Split(a)
)DT
SELECT ID,Passwords INTO #PasswordsINSERT
FRom (
SELECT Row_number()Over(Order by (SELECT NULL)) AS ID,Split.a.value('.', 'VARCHAR(1000)') AS Passwords
FROM (
SELECT CAST('<S>' + REPLACE(Passwords, ',', '</S><S>') + '</S>' AS XML) AS Passwords
FROM #USerName
) AS A
CROSS APPLY Passwords.nodes('/S') AS Split(a)
)DT
SELECT u.ID
,u.UserNAmes
,u.UserNAmes+'Db' AS DatabaseName
,p.Passwords
INTO #USerTable
FROM #USerNameINSERT u
INNER JOIN #PasswordsINSERT p ON p.ID = u.ID
DECLARE #minId INT
,#maxId INT
,#SqlQuery NVARCHAR(max)
,#SqlQuery1 NVARCHAR(max)
,#SqlQuery2 NVARCHAR(max)
SELECT #minId = MIN(ID)
,#maxId = Max(Id)
FROM #USerTable
WHILE (#minId <= #maxId)
BEGIN
SELECT #Usernameselect = UserNAmes
,#DatabaseNameselect = DatabaseName
,#PasswordSelect = Passwords
FROM #USerTable
WHERE ID = #minId
SET #SqlQuery = 'CREATE DATABASE ' + #DatabaseNameselect
SET #SqlQuery1 = 'USE [' + #DatabaseNameselect + ']'
SET #SqlQuery2 = 'CREATE LOGIN ' + #Usernameselect + ' WITH PASSWORD=N''' + #PasswordSelect + ''' MUST_CHANGE, CHECK_EXPIRATION=ON, CHECK_POLICY=ON'+ CHAR(13) + CHAR(10) + 'GO'
SET #SqlQuery = ISNULL('', 'GO') + CHAR(13) + CHAR(10) + #SqlQuery
+ CHAR(13) + CHAR(10) + 'GO' + CHAR(13) + CHAR(10) + #SqlQuery1
+ CHAR(13) + CHAR(10) + 'Go' + + CHAR(13) + CHAR(10) + #SqlQuery2
--EXEC (#SqlQuery)
PRINT #SqlQuery
SET #minId = #minId + 1
END

Use CREATE LOGIN command.
Following example will create user myDBUser.
USE [master]
GO
CREATE LOGIN [myDBUser] WITH PASSWORD=N'myPassword' MUST_CHANGE, DEFAULT_DATABASE=[myDB], CHECK_EXPIRATION=ON, CHECK_POLICY=ON
GO
And of course create DB user for such login
USE [myDB]
GO
CREATE USER myDBUser FOR LOGIN myDBUser;

I think something like this would work, you might need to alter the dynamic SQL bit around the login as its a bit thrown together.
--Create table for bulk insert
Create Table UserNameCSV (UserID int, UserName Varchar(100))
--Insert login names from C:\csvtest.txt
BULK
INSERT UserNameCSV
FROM 'c:\csvtest.txt'
WITH
(FIELDTERMINATOR = ',', ROWTERMINATOR = '\n')
GO
-- Run Cursor
Declare #UserName Varchar(100)
Declare db_Cursor CURSOR FAST_FORWARD FOR
Select UserName from UserNameCSV
OPEN db_Cursor
FETCH NEXT FROM db_Cursor INTO #UserName
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #Sql varchar(max) ='CREATE DATABASE ' + #UserName
DECLARE #Sql1 varchar(max) = 'USE [' + #UserName + ']'
DECLARE #Sql2 varchar(max) = 'CREATE LOGIN ' + #UserName + ' WITH PASSWORD=N''myPassword123!'' MUST_CHANGE, CHECK_EXPIRATION=ON, CHECK_POLICY=ON'
EXECUTE(#Sql)
EXECUTE (#Sql1)
EXECUTE (#Sql2)
FETCH NEXT FROM db_Cursor into #UserName
END
CLOSE db_Cursor
DEALLOCATE db_Cursor

Related

SQL query to run LDAP query to return AD listing of active users and then groups they are assigned to that start with GRP-XP%

I am trying to write a sql statement to control a report header selection of multiple database by user groups a user is assigned to. This is to limit the database selection security when running an SSRS report so that they can' only select their branch or group of branches they have access to. So far I can return the group results for a single user. I am trying to get a list of all active AD users and groups that are like GRP-XP%. Here is my script so far, that only works for a single username. Eventually this table will be passed to PowerBI, so I'd need username, usergroup table of listing complete.
Declare #username varchar(max) = 'ssmith'
DECLARE #Query NVARCHAR(1024), #Path NVARCHAR(1024)
SET #Query = '
SELECT #Path = distinguishedName
FROM OPENQUERY(CSAD, ''
SELECT distinguishedName, SAMAccountName
FROM ''''LDAP://DC=Domain,DC=co, dc=uk''''
WHERE
objectClass = ''''user''''
AND sAMAccountName = ''''' + Replace(#Username, 'domain\', '') + '''''
'')
'
EXEC SP_EXECUTESQL #Query, N'#Path NVARCHAR(1024) OUTPUT', #Path = #Path OUTPUT
SET #Query = '
SELECT
Replace(Right(cn, Len(cn)-7), '' '', '' '')
FROM OPENQUERY (CSAD, ''<LDAP://DC=Domain,DC=co,DC=uk>;(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=' + #Path +'));cn, adspath;subtree'')
where CN like ''GRP-XP%''
Order By cn'
Declare #table Table (Name varchar(100))
Insert into #table
EXEC SP_EXECUTESQL #Query
select * from #table
So the results would look like;
Thank you
I found some code I wrote many years ago. I can't test it as we no longer use a local AD domain controller but it definitely worked at some point.
It basically returns a list of all users and associated groups so it should be easy enough to modify for your needs.
ALTER PROC [AD].[Get_AD_AllUsersWithGroups]
AS
DECLARE #Query NVARCHAR(1024), #Path NVARCHAR(1024)
DECLARE #distinguishedName nvarchar(256)
DECLARE #SAMAccountName nvarchar(256)
CREATE TABLE #users (distinguishedName nvarchar(1000), SAMAccountName nvarchar(100))
CREATE TABLE #results(SAMAccountName nvarchar(100), DistinguishedName nvarchar(1000), GroupName nvarchar(1000), ActiveDirectoryPath nvarchar(1000))
-- Get all the users from AD
SET #Query = '
SELECT distinguishedName, SAMAccountName
FROM OPENQUERY(ADSI, ''
SELECT distinguishedName , SAMAccountName
FROM ''''LDAP://DC=MyDomain,DC=local''''
WHERE
objectClass = ''''user''''
'')
'
INSERT INTO #users
EXEC SP_EXECUTESQL #Query
-- For each user in #users, get a list of groups they belong to
DECLARE cUsers CURSOR FOR
SELECT distinguishedName, SAMAccountName from dbo.#users u
order by u.distinguishedName
OPEN cUsers
FETCH NEXT FROM cUsers
INTO #distinguishedName, #SAMAccountName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #distinguishedName = REPLACE(#distinguishedName, '''', '''''')
SET #SAMAccountName = REPLACE(#SAMAccountName, '''', '''''')
SET #Query = '
INSERT INTO #results
SELECT ''' + #SAMAccountName + ''', ''' + #distinguishedName + ''', cn as GroupName, AdsPath AS ActiveDirectoryPath
FROM OPENQUERY (ADSI, ''<LDAP://DC=MyDomain,DC=local>;(&(objectClass=group)(member:1.2.840.113556.1.4.1941:='
+ #distinguishedName +'));cn, adspath;subtree'')'
EXEC SP_EXECUTESQL #Query
FETCH NEXT FROM cUsers
INTO #distinguishedName, #SAMAccountName
END
CLOSE cUsers
DEALLOCATE cUsers
SELECT * FROM dbo.#results r
GO

Select a value from table for each database [duplicate]

I have (for testing purposes) many dbs with the same schema (=same tables and columns basically) on a sql server 2008 r2 instance.
i would like a query like
SELECT COUNT(*) FROM CUSTOMERS
on all DBs on the instance. I would like to have as result 2 columns:
1 - the DB Name
2 - the value of COUNT(*)
Example:
DBName // COUNT (*)
TestDB1 // 4
MyDB // 5
etc...
Note: i assume that CUSTOMERS table exists in all dbs (except master).
Try this one -
SET NOCOUNT ON;
IF OBJECT_ID (N'tempdb.dbo.#temp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp
(
[COUNT] INT
, DB VARCHAR(50)
)
DECLARE #TableName NVARCHAR(50)
SELECT #TableName = '[dbo].[CUSTOMERS]'
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = STUFF((
SELECT CHAR(13) + 'SELECT ' + QUOTENAME(name, '''') + ', COUNT(1) FROM ' + QUOTENAME(name) + '.' + QUOTENAME(#TableName)
FROM sys.databases
WHERE OBJECT_ID(QUOTENAME(name) + '.' + QUOTENAME(#TableName)) IS NOT NULL
FOR XML PATH(''), TYPE).value('text()[1]', 'NVARCHAR(MAX)'), 1, 1, '')
INSERT INTO #temp (DB, [COUNT])
EXEC sys.sp_executesql #SQL
SELECT *
FROM #temp t
Output (for example, in AdventureWorks) -
COUNT DB
----------- --------------------------------------------------
19972 AdventureWorks2008R2
19975 AdventureWorks2012
19472 AdventureWorks2008R2_Live
Straight forward query
EXECUTE sp_MSForEachDB
'USE ?; SELECT DB_NAME()AS DBName,
COUNT(1)AS [Count] FROM CUSTOMERS'
This query will show you what you want to see, but will also throw errors for each DB without a table called "CUSTOMERS". You will need to work out a logic to handle that.
Raj
How about something like this:
DECLARE c_db_names CURSOR FOR
SELECT name
FROM sys.databases
WHERE name NOT IN('master', 'tempdb') --might need to exclude more dbs
OPEN c_db_names
FETCH c_db_names INTO #db_name
WHILE ##Fetch_Status = 0
BEGIN
EXEC('
INSERT INTO #report
SELECT
''' + #db_name + '''
,COUNT(*)
FROM ' + #db_name + '..linkfile
')
FETCH c_db_names INTO #db_name
END
CLOSE c_db_names
DEALLOCATE c_db_names
SELECT * FROM #report
declare #userdb_list table (name varchar(4000) not null);
-- fill the db list with custom subset
insert into #userdb_list
select name from sys.databases --can add where condition to filter db names
declare
#curr_userdb varchar(300),
#db_placeholder varchar(300),
#final_db_exec_query varchar(max),
#query varchar(max);
set #query = '' -- <add ur query here>
set #db_placeholder = 'use {db}';
set #curr_userdb = (select min(name) from #userdb_list);
while #curr_userdb is not null
begin
set #final_db_exec_query = replace(#db_placeholder, '{db}', #curr_userdb + ' ' + #query);
exec (#final_db_exec_query);
--print #final_db_exec_query
set #curr_userdb = (select min(name) from #userdb_list where name > #curr_userdb);
end
GO
Solution without cursor - clean and simple
Because I know that a question was just referred to here that asked a slightly different question... if you only want to execute on certain databases, those databases could be stored in some table. Here I stored in a temporary table.
CREATE TABLE #Databases (
DbName varchar(255))
INSERT INTO #Databases (DbName)
Values ('GIS_NewJersey'), ('GIS_Pennsylvania')
DECLARE #command varchar(1000)
SELECT #command = 'Use [' + DbName + '];
Update sde.SAP_Load
SET FullAddress = CONCAT_WS('','', HouseNumber, Street, City, Postal, RegionName)
Update sde.PREMISE
SET FullAddress = CONCAT_WS('', '', HouseNumber, Street, City, Postal, RegionName)
Update sde.PREMISE_GEOCODE
SET FullAddress = CONCAT_WS('', '', HouseNumber, Street, City, Postal, RegionName)'
FROM #Databases
EXEC #command

How to use cursor correctly?

I have a script like this:
declare #username nvarchar(255)
declare #Alterstatement nvarchar(2000)
declare #userloginname nvarchar(255)
declare #InsertIntoHistory nvarchar(2000)
declare getusername cursor
for
select name from [SysAdmin].[dbo].[DisabledAccount]
where name in (select name from sys.server_principals)
open getusername
Fetch next from getusername into #username
while ##FETCH_STATUS=0
begin
set #userloginname = '[' + #username + ']'`
set #Alterstatement = 'Alter Login' +#userloginname +'Disable'
set #InsertIntoHistory = 'Insert into DisabledAccountHistory (DisabledName,ServerName) values('''
+ #username + ''','''+ ##servername +''')'
exec(#alterstatement)
exec(#InsertIntoHistory)
Fetch next from getusername
into #username
end
close getusername
deallocate getusername
I'm using this script to disable some users and insert into a history table. But when I run this, some problem shows up. For example when I have only one user that I need to disable, it will run 3 times and insert 3 rows into the history table. How can I ask it just run 1 time for each user?
I would get rid of the cursor completely as it isn't needed here. You can still disable all the logins and insert the data into your history table.
declare #SQL nvarchar(max) = ''
select #SQL = #SQL + 'ALTER LOGIN ' + QUOTENAME(name) + ' DISABLE;'
from [SysAdmin].[dbo].[DisabledAccount]
where name in (select name from sys.server_principals)
group by name
exec sp_executesql #SQL
Insert into DisabledAccountHistory
(
DisabledName
, ServerName
)
select name
, ##servername
from [SysAdmin].[dbo].[DisabledAccount]
where name in (select name from sys.server_principals)
group by name

Drop tables that starts with specific characters

I have multiple table names like g_str_a , g_str_ab , g_str_abc . I would like to drop all those tables that start with g_str on SQL Server 2008.
Will DROP Tables like 'g_str' help?
Please help me with the script.
SELECT
'DROP TABLE ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name) + ';'
FROM sys.tables
WHERE name LIKE 'g\_str%' ESCAPE '\'
Then review the script and run it.
You can also concatenate the result into a single string and execute with EXEC if you need an entirely automated solution.
You could use dynamic SQL:
DECLARE #SQL NVARCHAR(MAX) = '';
SELECT #SQL = #SQL + 'DROP TABLE ' + QUOTENAME(SCHEMA_NAME([Schema_ID])) + '.' + QUOTENAME([name]) + ';'
FROM sys.tables
WHERE Name LIKE 'g\_str%' ESCAPE('\');
EXECUTE SP_EXECUTESQL #SQL;
Following query will delete tables automatically:
BEGIN TRANSACTION
DECLARE #tmpTablesToDelete TABLE (
RowNumber INT PRIMARY KEY
,Query NVARCHAR(MAX)
)
INSERT INTO
#tmpTablesToDelete
SELECT
RowNumber = ROW_NUMBER() OVER (ORDER BY (SELECT (0)))
,'DROP TABLE '+schemas.name+'.'+objects.name AS Query
FROM
sys.objects
INNER JOIN
sys.schemas
ON
schemas.schema_id = objects.schema_id
WHERE
type = 'U' AND objects.name like 'g_str%'
DECLARE #Counter INT
SELECT #Counter = MAX(RowNumber) FROM #tmpTablesToDelete
WHILE(#Counter > 0) BEGIN
DECLARE #Query NVARCHAR(MAX)
SELECT #Query = Query FROM #tmpTablesToDelete WHERE RowNumber = #Counter
PRINT #Query
EXEC sp_executesql #statement = #Query
SET #Counter = #Counter - 1
END
COMMIT TRANSACTION

Converting Select results into Insert script - SQL Server

I have SQL Server 2008, SQL Server Management Studio.
I need to select data from a table in one database and insert into another table in another database.
How can I convert the returned results from my select into INSERT INTO ...?
Clarification from comments: While I believe this could be solved by a INSERT INTO SELECT or SELECT INTO, I do need to generate INSERT INTO ....
Here is another method, which may be easier than installing plugins or external tools in some situations:
Do a select [whatever you need]INTO temp.table_namefrom [... etc ...].
Right-click on the database in the Object Explorer => Tasks => Generate Scripts
Select temp.table_name in the "Choose Objects" screen, click Next.
In the "Specify how scripts should be saved" screen:
Click Advanced, find the "Types of data to Script" property, select "Data only", close the advanced properties.
Select "Save to new query window" (unless you have thousands of records).
Click Next, wait for the job to complete, observe the resulting INSERT statements appear in a new query window.
Use Find & Replace to change all [temp.table_name] to [your_table_name].
drop table [temp.table_name].
In SSMS:
Right click on the database > Tasks > Generate Scripts
Next
Select "Select specific database objects" and check the table you want scripted, Next
Click Advanced > in the list of options, scroll down to the bottom and look for the "Types of data to script" and change it to "Data Only" > OK
Select "Save to new query window" > Next > Next > Finish
All 180 rows now written as 180 insert statements!
Native method:
for example if you have table
Users(Id, name)
You can do this:
select 'insert into Table values(Id=' + Id + ', name=' + name + ')' from Users
1- Explanation of Scripts
A)Syntax for inserting data in table is as below
Insert into table(col1,col2,col3,col4,col5)
-- To achieve this part i
--have used below variable
------#CSV_COLUMN-------
values(Col1 data in quote, Col2..quote,..Col5..quote)
-- To achieve this part
-- i.e column data in
--quote i have used
--below variable
----#QUOTED_DATA---
C)To get above data from existing
table we have to write the select
query in such way that the output
will be in form of as above scripts
D)Then Finally i have Concatenated
above variable to create
final script that's will
generate insert script on execution
E)
#TEXT='SELECT ''INSERT INTO
'+#TABLE_NAME+'('+#CSV_COLUMN+')VALUES('''+'+'+SUBSTRING(#QUOTED_DATA,1,LEN(#QUOTED_DATA)-5)+'+'+''')'''+' Insert_Scripts FROM '+#TABLE_NAME + #FILTER_CONDITION
F)And Finally Executed the above query EXECUTE(TEXT)
G)QUOTENAME() function is used to wrap
column data inside quote
H)ISNULL is used because if any row has NULL
data for any column the query fails
and return NULL thats why to avoid
that i have used ISNULL
I)And created the sp sp_generate_insertscripts
for same
1- Just put the table name for which you want insert script
2- Filter condition if you want specific results
----------Final Procedure To generate Script------
CREATE PROCEDURE sp_generate_insertscripts
(
#TABLE_NAME VARCHAR(MAX),
#FILTER_CONDITION VARCHAR(MAX)=''
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #CSV_COLUMN VARCHAR(MAX),
#QUOTED_DATA VARCHAR(MAX),
#TEXT VARCHAR(MAX)
SELECT #CSV_COLUMN=STUFF
(
(
SELECT ',['+ NAME +']' FROM sys.all_columns
WHERE OBJECT_ID=OBJECT_ID(#TABLE_NAME) AND
is_identity!=1 FOR XML PATH('')
),1,1,''
)
SELECT #QUOTED_DATA=STUFF
(
(
SELECT ' ISNULL(QUOTENAME('+NAME+','+QUOTENAME('''','''''')+'),'+'''NULL'''+')+'','''+'+' FROM sys.all_columns
WHERE OBJECT_ID=OBJECT_ID(#TABLE_NAME) AND
is_identity!=1 FOR XML PATH('')
),1,1,''
)
SELECT #TEXT='SELECT ''INSERT INTO '+#TABLE_NAME+'('+#CSV_COLUMN+')VALUES('''+'+'+SUBSTRING(#QUOTED_DATA,1,LEN(#QUOTED_DATA)-5)+'+'+''')'''+' Insert_Scripts FROM '+#TABLE_NAME + #FILTER_CONDITION
--SELECT #CSV_COLUMN AS CSV_COLUMN,#QUOTED_DATA AS QUOTED_DATA,#TEXT TEXT
EXECUTE (#TEXT)
SET NOCOUNT OFF
END
SSMS Toolpack (which is FREE as in beer) has a variety of great features - including generating INSERT statements from tables.
Update: for SQL Server Management Studio 2012 (and newer), SSMS Toolpack is no longer free, but requires a modest licensing fee.
It's possible to do via Visual Studio SQL Server Object Explorer.
You can click "View Data" from context menu for necessary table, filter results and save result as script.
Using visual studio, do the following
Create a project of type SQL Server-->SQL Server Database Project
open the sql server explorer CTL-\ , CTL-S
add a SQL Server by right clicking on the SQL SERVER icon. Selcet ADD NEW SERVER
navigate down to the table you are interested in
right click--> VIEW DATA
Click the top left cell to highlight everything (ctl-A doesnt seem to work)
Right Click -->SCript
This is fabulous. I have tried everything listed above over the years. I know there is a tool out there that will do this and much more, cant think of the name of it. But it is very expensive.
Good luck. I just figured this out. Have not tested it extensively w/ text fields etc, but it looks like it gets you a long ways down the road.
Greg
Create a separate table using into statement
For example
Select * into Test_123 from [dbo].[Employee] where Name like '%Test%'
Go to the Database
Right Click the Database
Click on Generate Script
Select your table
Select advanace option and select the Attribute "Data Only"
Select the file "open in new query"
Sql will generate script for you
This is a more versatile solution (that can do a little more than the question asks), and can be used in a query window without having to create a new stored proc - useful in production databases for instance where you don't have write access.
To use the code, please modify according to the in line comments which explain its usage. You can then just run this query in a query window and it will print the INSERT statements you require.
SET NOCOUNT ON
-- Set the ID you wish to filter on here
DECLARE #id AS INT = 123
DECLARE #tables TABLE (Name NVARCHAR(128), IdField NVARCHAR(128), IdInsert BIT, Excluded NVARCHAR(128))
-- Add any tables you wish to generate INSERT statements for here. The fields are as thus:
-- Name: Your table name
-- IdField: The field on which to filter the dataset
-- IdInsert: If the primary key field is to be included in the INSERT statement
-- Excluded: Any fields you do not wish to include in the INSERT statement
INSERT INTO #tables (Name, IdField, IdInsert, Excluded) VALUES ('MyTable1', 'Id', 0, 'Created,Modified')
INSERT INTO #tables (Name, IdField, IdInsert, Excluded) VALUES ('MyTable2', 'Id', 1, 'Created,Modified')
DECLARE #numberTypes TABLE (sysId TINYINT)
-- This will ensure INT and BIT types are not surrounded with quotes in the
-- resultant INSERT statement, but you may need to add more (from sys.types)
INSERT #numberTypes(SysId) VALUES(56),(104)
DECLARE #rows INT = (SELECT COUNT(*) FROM #tables)
DECLARE #cnt INT = 1
DECLARE #results TABLE (Sql NVARCHAR(4000))
WHILE #cnt <= #rows
BEGIN
DECLARE #tablename AS NVARCHAR(128)
DECLARE #idField AS NVARCHAR(128)
DECLARE #idInsert AS BIT
DECLARE #excluded AS NVARCHAR(128)
SELECT
#tablename = Name,
#idField = IdField,
#idInsert = IdInsert,
#excluded = Excluded
FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS RowId FROM #tables) t WHERE t.RowId = #cnt
DECLARE #excludedFields TABLE (FieldName NVARCHAR(128))
DECLARE #xml AS XML = CAST(('<X>' + REPLACE(#excluded, ',', '</X><X>') + '</X>') AS XML)
INSERT INTO #excludedFields SELECT N.value('.', 'NVARCHAR(128)') FROM #xml.nodes('X') AS T(N)
DECLARE #setIdentity NVARCHAR(128) = 'SET IDENTITY_INSERT ' + #tablename
DECLARE #execsql AS NVARCHAR(4000) = 'SELECT ''' + CASE WHEN #idInsert = 1 THEN #setIdentity + ' ON' + CHAR(13) ELSE '' END + 'INSERT INTO ' + #tablename + ' ('
SELECT #execsql = #execsql +
STUFF
(
(
SELECT CASE WHEN NOT EXISTS(SELECT * FROM #excludedFields WHERE FieldName = name) THEN ', ' + name ELSE '' END
FROM sys.columns
WHERE object_id = OBJECT_ID('dbo.' + #tablename)
FOR XML PATH('')
), 1, 2, ''
) +
')' + CHAR(13) + 'VALUES (' +
STUFF
(
(
SELECT
CASE WHEN NOT EXISTS(SELECT * FROM #excludedFields WHERE FieldName = name) THEN
''', '' + ISNULL(' +
CASE WHEN EXISTS(SELECT * FROM #numberTypes WHERE SysId = system_type_id) THEN '' ELSE ''''''''' + ' END +
'CAST(' + name + ' AS VARCHAR)' +
CASE WHEN EXISTS(SELECT * FROM #numberTypes WHERE SysId = system_type_id) THEN '' ELSE ' + ''''''''' END +
', ''NULL'') + '
ELSE ''
END
FROM sys.columns
WHERE object_id = OBJECT_ID('dbo.' + #tablename)
FOR XML PATH('')
), 1, 3, ''
) +
''')' + CASE WHEN #idInsert = 1 THEN CHAR(13) + #setIdentity + ' OFF' ELSE '' END +
''' FROM ' + #tablename + ' WHERE ' + #idField + ' = ' + CAST(#id AS VARCHAR)
INSERT #results EXEC (#execsql)
DELETE #excludedFields
SET #cnt = #cnt + 1
END
DECLARE cur CURSOR FOR SELECT Sql FROM #results
OPEN cur
DECLARE #sql NVARCHAR(4000)
FETCH NEXT FROM cur INTO #sql
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #sql
FETCH NEXT FROM cur INTO #sql
END
CLOSE cur
DEALLOCATE cur
You can Choose 'Result to File' option in SSMS and export your select result to file and make your changes in result file and finally using BCP - Bulk copy you can insert in table 1 in database 2.
I think for bulk insert you have to convert .rpt file to .csv file
Hope it will help.
I had a similar problem, but I needed to be able to create an INSERT statement from a query (with filters etc.)
So I created following procedure:
CREATE PROCEDURE dbo.ConvertQueryToInsert (#input NVARCHAR(max), #target NVARCHAR(max)) AS BEGIN
DECLARE #fields NVARCHAR(max);
DECLARE #select NVARCHAR(max);
-- Get the defintion from sys.columns and assemble a string with the fields/transformations for the dynamic query
SELECT
#fields = COALESCE(#fields + ', ', '') + '[' + name +']',
#select = COALESCE(#select + ', ', '') + ''''''' + ISNULL(CAST([' + name + '] AS NVARCHAR(max)), ''NULL'')+'''''''
FROM tempdb.sys.columns
WHERE [object_id] = OBJECT_ID(N'tempdb..'+#input);
-- Run the a dynamic query with the fields from #select into a new temp table
CREATE TABLE #ConvertQueryToInsertTemp (strings nvarchar(max))
DECLARE #stmt NVARCHAR(max) = 'INSERT INTO #ConvertQueryToInsertTemp SELECT '''+ #select + ''' AS [strings] FROM '+#input
exec sp_executesql #stmt
-- Output the final insert statement
SELECT 'INSERT INTO ' + #target + ' (' + #fields + ') VALUES (' + REPLACE(strings, '''NULL''', 'NULL') +')' FROM #ConvertQueryToInsertTemp
-- Clean up temp tables
DROP TABLE #ConvertQueryToInsertTemp
SET #stmt = 'DROP TABLE ' + #input
exec sp_executesql #stmt
END
You can then use it by writing the output of your query into a temp table and running the procedure:
-- Example table
CREATE TABLE Dummy (Id INT, Comment NVARCHAR(50), TimeStamp DATETIME)
INSERT INTO Dummy VALUES (1 , 'Foo', GetDate()), (2, 'Bar', GetDate()), (3, 'Foo Bar', GetDate())
-- Run query and procedure
SELECT * INTO #TempTableForConvert FROM Dummy WHERE Id < 3
EXEC dbo.ConvertQueryToInsert '#TempTableForConvert', 'dbo.Dummy'
Note:
This procedure only casts the values to a string which can cause the data to look a bit different. With DATETIME for example the seconds will be lost.
I created the following procedure:
if object_id('tool.create_insert', 'P') is null
begin
exec('create procedure tool.create_insert as');
end;
go
alter procedure tool.create_insert(#schema varchar(200) = 'dbo',
#table varchar(200),
#where varchar(max) = null,
#top int = null,
#insert varchar(max) output)
as
begin
declare #insert_fields varchar(max),
#select varchar(max),
#error varchar(500),
#query varchar(max);
declare #values table(description varchar(max));
set nocount on;
-- Get columns
select #insert_fields = isnull(#insert_fields + ', ', '') + c.name,
#select = case type_name(c.system_type_id)
when 'varchar' then isnull(#select + ' + '', '' + ', '') + ' isnull('''''''' + cast(' + c.name + ' as varchar) + '''''''', ''null'')'
when 'datetime' then isnull(#select + ' + '', '' + ', '') + ' isnull('''''''' + convert(varchar, ' + c.name + ', 121) + '''''''', ''null'')'
else isnull(#select + ' + '', '' + ', '') + 'isnull(cast(' + c.name + ' as varchar), ''null'')'
end
from sys.columns c with(nolock)
inner join sys.tables t with(nolock) on t.object_id = c.object_id
inner join sys.schemas s with(nolock) on s.schema_id = t.schema_id
where s.name = #schema
and t.name = #table;
-- If there's no columns...
if #insert_fields is null or #select is null
begin
set #error = 'There''s no ' + #schema + '.' + #table + ' inside the target database.';
raiserror(#error, 16, 1);
return;
end;
set #insert_fields = 'insert into ' + #schema + '.' + #table + '(' + #insert_fields + ')';
if isnull(#where, '') <> '' and charindex('where', ltrim(rtrim(#where))) < 1
begin
set #where = 'where ' + #where;
end
else
begin
set #where = '';
end;
set #query = 'select ' + isnull('top(' + cast(#top as varchar) + ')', '') + #select + ' from ' + #schema + '.' + #table + ' with (nolock) ' + #where;
insert into #values(description)
exec(#query);
set #insert = isnull(#insert + char(10), '') + '--' + upper(#schema + '.' + #table);
select #insert = #insert + char(10) + #insert_fields + char(10) + 'values(' + v.description + ');' + char(10) + 'go' + char(10)
from #values v
where isnull(v.description, '') <> '';
end;
go
Then you can use it that way:
declare #insert varchar(max),
#part varchar(max),
#start int,
#end int;
set #start = 1;
exec tool.create_insert #schema = 'dbo',
#table = 'customer',
#where = 'id = 1',
#insert = #insert output;
-- Print one line to avoid the maximum 8000 characters problem
while len(#insert) > 0
begin
set #end = charindex(char(10), #insert);
if #end = 0
begin
set #end = len(#insert) + 1;
end;
print substring(#insert, #start, #end - 1);
set #insert = substring(#insert, #end + 1, len(#insert) - #end + 1);
end;
The output would be something like that:
--DBO.CUSTOMER
insert into dbo.customer(id, name, type)
values(1, 'CUSTOMER NAME', 'F');
go
If you just want to get a range of rows, use the #top parameter as bellow:
declare #insert varchar(max),
#part varchar(max),
#start int,
#end int;
set #start = 1;
exec tool.create_insert #schema = 'dbo',
#table = 'customer',
#top = 100,
#insert = #insert output;
-- Print one line to avoid the maximum 8000 characters problem
while len(#insert) > 0
begin
set #end = charindex(char(10), #insert);
if #end = 0
begin
set #end = len(#insert) + 1;
end;
print substring(#insert, #start, #end - 1);
set #insert = substring(#insert, #end + 1, len(#insert) - #end + 1);
end;
You can Use Sql Server Integration Service Packages specifically designed for Import and Export operation.
VS has a package for developing these packages if your fully install Sql Server.
Integration Services in Business Intelligence Development Studio
I think its also possible with adhoc queries
you can export result to excel file and then import that file into your datatable object or use it as it is and then import the excel file into the second database
have a look at this link
this can help u alot.
http://vscontrols.blogspot.com/2010/09/import-and-export-excel-to-sql-server.html
If you are using Oracle (or configure the application to the SQL Server) then Oracle SQL Developer does this for you. choose 'unload' for a table and follow the options through (untick DDL if you don't want all the table create stuff).
I found this SMSMS Boost addon, which is free and does exactly this among other things. You can right click on the results and select Script data as.
You can use this Q2C.SSMSPlugin, which is free and open source. You can right click and select "Execute Query To Command... -> Query To Insert...". Enjoy)
You can use an INSERT INTO SELECT statement, to insert the results of a select query into a table. http://www.w3schools.com/sql/sql_insert_into_select.asp
Example:
INSERT INTO Customers (CustomerName, Country)
SELECT SupplierName, Country
FROM Suppliers
WHERE Country='Germany'