SQL Server - copy stored procedures from one db to another - sql

I am new to SQL, and what I needed to do was to combine 2 .mdf databases into one. I did that using SQL Server 2008 Manager - Tasks > Import/Export tables.The tables and views were copied successfully, but there are no Stored procedures in the new database. Is there any way to do that?

Right click on database
Tasks
Generate Scripts
Select the objects you wish to script
Script to File
Run generated scripts against target database

This code copies all stored procedures in the Master database to the target database, you can copy just the procedures you like by filtering the query on procedure name.
#sql is defined as nvarchar(max), #Name is the target database
DECLARE c CURSOR FOR
SELECT Definition
FROM [ResiDazeMaster].[sys].[procedures] p
INNER JOIN [ResiDazeMaster].sys.sql_modules m ON p.object_id = m.object_id
OPEN c
FETCH NEXT FROM c INTO #sql
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = REPLACE(#sql,'''','''''')
SET #sql = 'USE [' + #Name + ']; EXEC(''' + #sql + ''')'
EXEC(#sql)
FETCH NEXT FROM c INTO #sql
END
CLOSE c
DEALLOCATE c

Late one but gives more details that might be useful…
Here is a list of things you can do with advantages and disadvantages
Generate scripts using SSMS
Pros: extremely easy to use and supported by default
Cons: scripts might not be in the correct execution order and you might get errors if stored procedure already exists on secondary database. Make sure you review the script before executing.
Third party tools
Pros: tools such as ApexSQL Diff (this is what I use but there are many others like tools from Red Gate or Dev Art) will compare two databases in one click and generate script that you can execute immediately
Cons: these are not free (most vendors have a fully functional trial though)
System Views
Pros: You can easily see which stored procedures exist on secondary server and only generate those you don’t have.
Cons: Requires a bit more SQL knowledge
Here is how to get a list of all procedures in some database that don’t exist in another database
select *
from DB1.sys.procedures P
where P.name not in
(select name from DB2.sys.procedures P2)

I originally found this post looking for a solution to copying stored procedures from my remote production database to my local development database. After success using the suggested approach in this thread, I realized I grew increasingly lazy (or resourceful, whichever you prefer) and wanted this to be automated. I came across this link, which proved to be very helpful (thank you vincpa), and I extended upon it, resulting in the following file (schema_backup.ps1):
$server = "servername"
$database = "databaseName"
$output_path = "D:\prod_schema_backup"
$login = "username"
$password = "password"
$schema = "dbo"
$table_path = "$output_path\table\"
$storedProcs_path = "$output_path\stp\"
$views_path = "$output_path\view\"
$udfs_path = "$output_path\udf\"
$textCatalog_path = "$output_path\fulltextcat\"
$udtts_path = "$output_path\udtt\"
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | out-null
$srvConn = new-object Microsoft.SqlServer.Management.Common.ServerConnection
$srvConn.ServerInstance = $server
$srvConn.LoginSecure = $false
$srvConn.Login = $login
$srvConn.Password = $password
$srv = New-Object Microsoft.SqlServer.Management.SMO.Server($srvConn)
$db = New-Object ("Microsoft.SqlServer.Management.SMO.Database")
$tbl = New-Object ("Microsoft.SqlServer.Management.SMO.Table")
$scripter = New-Object Microsoft.SqlServer.Management.SMO.Scripter($srvConn)
# Get the database and table objects
$db = $srv.Databases[$database]
$tbl = $db.tables | Where-object { $_.schema -eq $schema -and -not $_.IsSystemObject }
$storedProcs = $db.StoredProcedures | Where-object { $_.schema -eq $schema -and -not $_.IsSystemObject }
$views = $db.Views | Where-object { $_.schema -eq $schema }
$udfs = $db.UserDefinedFunctions | Where-object { $_.schema -eq $schema -and -not $_.IsSystemObject }
$catlog = $db.FullTextCatalogs
$udtts = $db.UserDefinedTableTypes | Where-object { $_.schema -eq $schema }
# Set scripter options to ensure only data is scripted
$scripter.Options.ScriptSchema = $true;
$scripter.Options.ScriptData = $false;
#Exclude GOs after every line
$scripter.Options.NoCommandTerminator = $false;
$scripter.Options.ToFileOnly = $true
$scripter.Options.AllowSystemObjects = $false
$scripter.Options.Permissions = $true
$scripter.Options.DriAllConstraints = $true
$scripter.Options.SchemaQualify = $true
$scripter.Options.AnsiFile = $true
$scripter.Options.SchemaQualifyForeignKeysReferences = $true
$scripter.Options.Indexes = $true
$scripter.Options.DriIndexes = $true
$scripter.Options.DriClustered = $true
$scripter.Options.DriNonClustered = $true
$scripter.Options.NonClusteredIndexes = $true
$scripter.Options.ClusteredIndexes = $true
$scripter.Options.FullTextIndexes = $true
$scripter.Options.EnforceScriptingOptions = $true
function CopyObjectsToFiles($objects, $outDir) {
#clear out before
Remove-Item $outDir* -Force -Recurse
if (-not (Test-Path $outDir)) {
[System.IO.Directory]::CreateDirectory($outDir)
}
foreach ($o in $objects) {
if ($o -ne $null) {
$schemaPrefix = ""
if ($o.Schema -ne $null -and $o.Schema -ne "") {
$schemaPrefix = $o.Schema + "."
}
#removed the next line so I can use the filename to drop the stored proc
#on the destination and recreate it
#$scripter.Options.FileName = $outDir + $schemaPrefix + $o.Name + ".sql"
$scripter.Options.FileName = $outDir + $schemaPrefix + $o.Name
Write-Host "Writing " $scripter.Options.FileName
$scripter.EnumScript($o)
}
}
}
# Output the scripts
CopyObjectsToFiles $tbl $table_path
CopyObjectsToFiles $storedProcs $storedProcs_path
CopyObjectsToFiles $views $views_path
CopyObjectsToFiles $catlog $textCatalog_path
CopyObjectsToFiles $udtts $udtts_path
CopyObjectsToFiles $udfs $udfs_path
Write-Host "Finished at" (Get-Date)
$srv.ConnectionContext.Disconnect()
I have a .bat file that calls this, and is called from Task Scheduler. After the call to the Powershell file, I have:
for /f %f in ('dir /b d:\prod_schema_backup\stp\') do sqlcmd /S localhost /d dest_db /Q "DROP PROCEDURE %f"
That line will go thru the directory and drop the procedures it is going to recreate. If this wasn't a development environment, I would not like programmatically dropping procedures this way. I then rename all the stored procedure files to have .sql:
powershell Dir d:\prod_schema_backup\stp\ | Rename-Item -NewName { $_.name + ".sql" }
And then run:
for /f %f in ('dir /b d:\prod_schema_backup\stp\') do sqlcmd /S localhost /d dest_db /E /i "%f".sql
And that iterates through all the .sql files and recreates the stored procedures. I hope that any part of this will prove to be helpful to someone.

use
select * from sys.procedures
to show all your procedures;
sp_helptext #objname = 'Procedure_name'
to get the code
and your creativity to build something to loop through them all and generate the export code :)

You can use SSMS's "Generate Scripts..." function to script out whatever you need to transfer. Right-click on the source database in SSMS, choose "Generate Scripts...", and follow the wizard along. Then run your resultant script that will now contain the stored procedure create statements.

You can generate scriptof the stored proc's as depicted in other answers. Once the script have been generated, you can use sqlcmd to execute them against target DB like
sqlcmd -S <server name> -U <user name> -d <DB name> -i <script file> -o <output log file>

Another option is to transfer stored procedures using SQL Server Integration Services (SSIS). There is a task called Transfer SQL Server Objects Task. You can use the task to transfer the following items:
Tables
Views
Stored Procedures
User-Defined Functions
Defaults
User-Defined Data Types
Partition Functions
Partition Schemes
Schemas
Assemblies
User-Defined Aggregates
User-Defined Types
XML Schema Collection
It's a graphical tutorial for Transfer SQL Server Objects Task.

In Mgmt Studio, right-click on your original database then Tasks then Generate Scripts... - follow the wizard.

SELECT definition + char(13) + 'GO' FROM MyDatabase.sys.sql_modules s INNER JOIN MyDatabase.sys.procedures p ON [s].[object_id] = [p].[object_id] WHERE p.name LIKE 'Something%'" queryout "c:\SP_scripts.sql -S MyInstance -T -t -w
get the sp and execute it

-- This program copies (CREATE OR ALTER) a single PROCEDURE from one database to another
declare #SourceDatabase nvarchar(50);
declare #SourceSchemaName nvarchar(50)
declare #TargetDatabase nvarchar(50);
declare #ProceduresName nvarchar(50);
declare #sql nvarchar(max)
set #SourceDatabase = N'Northwind' -- The name of the source database
set #SourceSchemaName = N'dbo' -- The name of Procedure SCHEME
set #ProceduresName = N'CustOrderHist' -- The name of Procedure
set #TargetDatabase = N'AdventureWorks' -- The name of the Target database
-- -------- - - -
-- If the PROCEDURE SCHEME does not exist, create it
set #sql = ' use [' +#TargetDatabase +'] ' +
' IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = ''' + #SourceSchemaName+''') '+
' BEGIN ' +
' EXEC('' CREATE SCHEMA '+ #SourceSchemaName +''') ' +
' END'
exec (#sql);
set #sql = ''
--
set #sql = #sql + ' use [' + #TargetDatabase +'] ;' +
' declare #sql2 nvarchar(max) ;' +
' SELECT #sql2 = coalesce(#sql2,'';'' ) + [definition] + '' ; '' ' +
' FROM ['+#sourceDatabase+'].[sys].[procedures] p ' +
' INNER JOIN ['+#sourceDatabase+'].sys.sql_modules m ON p.object_id = m.object_id '+
' where SCHEMA_NAME([schema_id]) = ''' +#SourceSchemaName +''' and [name] = N''' + #ProceduresName + ''' ; ' +
' set #sql2 = replace(#sql2,''CREATE PROCEDURE'',''CREATE OR ALTER PROCEDURE'')' +
' exec (#sql2)'
exec (#sql)

Related

Sql Query Generation Using bat file

I have a requirement where i need to see data for every week using a sql query.
I used query like SELECT * from table Between '27-08-2012' and '30-08-2012'.
Now my requirement is that i need a batch file that can given me this script based on user selection. Like user can give start date and end date and sql query should generate automatically.
A much less error prone way to get a date range is to use a graphical date picker
than manual user input which has to be checked for validity.
(month/day names will match your locale, not my German one)
This PowerShell script:
# Function Pick-Date
[void][System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
Function Pick-Date {
$Cal = new-object System.Windows.Forms.MonthCalendar
$Cal.ShowWeekNumbers = $true
$Cal.MaxSelectionCount = 10 # change this value for the max date distance
$Cal.Dock = 'Fill'
$Form = new-object Windows.Forms.Form
$Form.text = "Drag the mouse to select a date range then hit [enter]"
$Form.Size = new-object Drawing.Size #(656,620)
$btnSelect = new-object System.Windows.Forms.Button
$btnSelect.Size = "1,1"
$btnSelect.add_Click({ $Form.close() })
$Form.Controls.Add($btnSelect )
$Form.AcceptButton = $btnSelect
$Form.Controls.Add($Cal)
$Form.Add_Shown({$Form.Activate()})
[void]$Form.showdialog()
return ("SELECT * from table Between '"+
(Get-Date($Cal.SelectionStart) -format 'dd-MM-yyyy')+
"' and '"+
(Get-Date($Cal.SelectionEnd) -format 'dd-MM-yyyy')+
"'")
}
Pick-Date
Will have this output, you can save to a file.sql
PS> .\Pick-Date.ps1
SELECT * from table Between '27-08-2012' and '31-08-2012'
EDIT
This batch wrapper for the powerShell script will store the query in the variable SqlQuery
#Echo off&SetLocal EnableExtensions EnableDelayedExpansion
::Wrap Pick-Date.ps1 in same folder as batch
For /F "delims=" %%%A in (
'Powershell -NoP -NonI -NoLogo -File Pick-Date.ps1 '
) Do Set "SqlQuery=%%A"
Set SqlQuery

invoke-expression for SQLCMD -i "test.sql" and put results to a variable

I have a huge sql query where I want to run on a remote server from another server via powershell, however I am having trouble trying get the results per column per row of since test.sql produces a table with multiple table and result. I know I can query it using the
$ConnectionToServer = New-Object System.Data.SQLClient.SQLConnection
$CommandCMSQry = New-Object System.Data.SQLClient.SQLCommand
Where $CommandCMSQry contains the whole query in a string format. However, I am trying lessen the rows of the script thus I wanted to put the SQL query outside of the PS script.
$QryPath = "D:\CNA\DatabaseIntegrityCheck.sql"
invoke-expression "SQLCMD -E -S $InstanceNm -d 'master' -i $QryPath -b" | Tee-Object -Variable ResultCreateSP | Select-Object name,database_id
$ResultCreateSP
Example result:
main result
a b
1 foo1
2 foo2
and if I access the columns something with like this
write-host "a = " + $ResultCreateSP.name + "b = " + $ResultCreateSP.database_id
a = 1 b = foo1

How to create text files using table content for name and text inside in SQL Server

I have following table:
1 One TEXT_ONE
2 Two TEXT_TWO
3 Three TEXT_Three ...
I want run SQL Query that will creates txt files in specific folder:
C:\Files\One.txt (Text inside - TEXT_ONE)
C:\Files\Two.txt (Text inside - TEXT_TWO)
C:\Files\Three.txt (Text inside - TEXT_Three)...
I'm not so good in SQL, so any help appreciates=)
Thanks
I found my own way. It's probably not absolute answer for my question, but the idea completed.
So, I've created bcp Command that needs to be executed from Command Line
'bcp "SELECT ColumnName FROM DBName.schema.TableName WHERE IDCol = ' + CAST(IDCol as varchar(2)) + '" QUERYOUT .\' + ColumnForFileName + '.txt -FullServerName -T -c'
You can run select statement in SQL. Here is my example:
SELECT sp.[SessionPageID]
,sp.[SummaryBody]
,sp.[MainTableBody]
,sf.[FileName]
,'bcp "SELECT SummaryBody FROM WLS_3E_TIMELOAD_APP.dbo.SessionPage WHERE SessionPageID = ' + CAST(sp.[SessionPageID] as varchar(2)) + '" QUERYOUT .\SB_' + sf.[FileName] + '_Session.txt -SCHAKHAU-T430\CHAKHAU -T -c'
,'bcp "SELECT MainTableBody FROM WLS_3E_TIMELOAD_APP.dbo.SessionPage" QUERYOUT .\MB_' + sf.[FileName] + '_Session.txt -MYLapTOP\LOCAL -T -c'
FROM [SessionPage] sp
JOIN SourceFile sf ON sf.SourceFileID = sp.SourceFileID
If you run this kind of query in result you will get all your bcp commands, so you then can execute them from Command Line

Powershell and SQL Server - set nocount

I am writing a powershell function to retrieve a list of students from our database but the first item returned is always the number of records. I can't figure out a way to incorporate the set nocount on into the the script - any ideas?
The function so far is:
Function CheckMIS{
$Table = new-object System.Data.DataTable
$sqlConn = new-object System.Data.SqlClient.SqlConnection("Server=blah blah")
$adapter = new-object System.Data.SqlClient.SqlDataAdapter(
"select txtSchoolID,
intSystemStatus,
txtForename, txtSurname,
txtForm
from TblPupils
where intSystemStatus = 1 ",$sqlConn)
$adapter.Fill($Table)
$sqlConn.Close()
write-output $table
}
It returns a lovely table - but the first line is always the number of records first.
I just need to suppress that output.
You could catch the rowcount for later use.
$rowCount = $adapter.Fill($Table)
Or just ignore it.
$adapter.Fill($Table) | Out-Null
Adding "Set Nocount On; select txtSchoolID,"... didn't have any effect in my test.
You should be able to just add SET NOCOUNT ON to your SQL.
i.e. SET NOCOUNT ON select txtSchoolId, intSystemStatus,
txtForename, txtSurname,
txtForm
from TblPupils
where intSystemStatus = 1

Save Sql Recordset into the Flat text file?

i need to dump my sql query result into the text file. i have created the following query,
DECLARE #cmd VARCHAR(2048)
SET #cmd = 'OSQL -localhost -CRN370 '
+ ' -UCRN370 -PCRN370'
+ ' -Q"SELECT TOP 5 GageId FROM EwQMS370..msgages"'
+ ' -oc:\authors.txt'
EXEC master..xp_cmdshell #cmd, NO_OUTPUT
The above query created the text file authors.txt. But the content of the file shows the following error message
" Error: Conflicting switches : -U and -E "
Any help really appreciated
Start -> Run... -> cmd
And try to execute this command without -o key and its value :)
I think problem is with command parameters.
And what is the parameter "-localhost". Beybe you forgot about S key? And what is the -C parameter key?
Try this:
DECLARE #cmd VARCHAR(2048)
SET #cmd = 'OSQL -Slocalhost '
+ ' -UCRN370 -PCRN370'
+ ' -Q"SELECT TOP 5 GageId FROM EwQMS370..msgages"'
+ ' -oc:\authors.txt'
EXEC master..xp_cmdshell #cmd, NO_OUTPUT