Ответ 1
Просто прочитайте вывод SELECT NAME из SYS.PROCEDURES, затем вызовите EXEC sp_HelpText SPNAME для каждой хранимой процедуры, вы получите набор записей с одной строкой текста в строке.
Есть ли способ получить хранимые процедуры из базы данных SQL Server 2005 Express с помощью С#? Я хотел бы экспортировать все эти данные таким же образом, что вы можете script использовать наш SQL Server Management Studio без установки GUI.
Я видел некоторые ссылки, чтобы делать что-то с помощью PowerShell, но в конце концов консольное приложение на С# - это то, что я действительно хочу.
Чтобы уточнить....
Я хочу script выполнить хранимые процедуры. Список через Select * from sys.procedures
полезен, но в конце мне нужно script вывести каждый из них.
Просто прочитайте вывод SELECT NAME из SYS.PROCEDURES, затем вызовите EXEC sp_HelpText SPNAME для каждой хранимой процедуры, вы получите набор записей с одной строкой текста в строке.
Для этого вы можете использовать SMO. Прежде всего, добавьте ссылки на эти сборки в свой проект:
Они расположены в GAC (найдите папку C:\WINDOWS\assembly).
В качестве примера хранимых процедур сценариев используйте следующий код:
using System;
using System.Collections.Generic;
using System.Data;
using Microsoft.SqlServer.Management.Smo;
class Program
{
static void Main(string[] args)
{
Server server = new Server(@".\SQLEXPRESS");
Database db = server.Databases["Northwind"];
List<SqlSmoObject> list = new List<SqlSmoObject>();
DataTable dataTable = db.EnumObjects(DatabaseObjectTypes.StoredProcedure);
foreach (DataRow row in dataTable.Rows)
{
string sSchema = (string)row["Schema"];
if (sSchema == "sys" || sSchema == "INFORMATION_SCHEMA")
continue;
StoredProcedure sp = (StoredProcedure)server.GetSmoObject(
new Urn((string)row["Urn"]));
if (!sp.IsSystemObject)
list.Add(sp);
}
Scripter scripter = new Scripter();
scripter.Server = server;
scripter.Options.IncludeHeaders = true;
scripter.Options.SchemaQualify = true;
scripter.Options.ToFileOnly = true;
scripter.Options.FileName = @"C:\StoredProcedures.sql";
scripter.Script(list.ToArray());
}
}
См. также: SQL Server: основы для сценариев SMO.
Это сообщение в блоге предлагает запустить это против вашей базы данных:
select * from sys.procedures
;WITH ROUTINES AS (
-- CANNOT use INFORMATION_SCHEMA.ROUTINES because of 4000 character limit
SELECT o.type_desc AS ROUTINE_TYPE
,o.[name] AS ROUTINE_NAME
,m.definition AS ROUTINE_DEFINITION
FROM sys.sql_modules AS m
INNER JOIN sys.objects AS o
ON m.object_id = o.object_id
)
SELECT *
FROM ROUTINES
Вы можете использовать:
DataTable dtProcs = sqlConn.GetSchema("Procedures", new string[] { databaseName });
DataTable dtProcParams = sqlConn.GetSchema("ProcedureParameters", new string[] { databaseName });
Вы также можете получить любую другую информацию о схеме, такую как таблицы, индексы и т.д., если они вам понадобятся.
Вы можете получить информацию о GetSchema() здесь и информацию о коллекциях схем SQL Server здесь
Изменить: Извините, это не помогает при написании этой информации, но я думаю, что это полезная информация.
public static void GenerateTableScript()
{
Server databaseServer = default(Server);//DataBase Server Name
databaseServer = new Server("yourDatabase Server Name");
string strFileName = @"C:\Images\Your FileName_" + DateTime.Today.ToString("yyyyMMdd") + ".sql"; //20120720`enter code here
if (System.IO.File.Exists(strFileName))
System.IO.File.Delete(strFileName);
List<SqlSmoObject> list = new List<SqlSmoObject>();
Scripter scripter = new Scripter(databaseServer);
Database dbUltimateSurvey = databaseServer.Databases["YourDataBaseName"];//DataBase Name
//Table scripting Writing
DataTable dataTable1 = dbUltimateSurvey.EnumObjects(DatabaseObjectTypes.Table);
foreach (DataRow drTable in dataTable1.Rows)
{
//string strTableSchema = (string)drTable["Schema"];
//if (strTableSchema == "dbo")
// continue;
Table dbTable = (Table)databaseServer.GetSmoObject(new Urn((string)drTable["Urn"]));
if (!dbTable.IsSystemObject)
if (dbTable.Name.Contains("SASTool_"))
list.Add(dbTable);
}
scripter.Server = databaseServer;
scripter.Options.IncludeHeaders = true;
scripter.Options.SchemaQualify = true;
scripter.Options.ToFileOnly = true;
scripter.Options.FileName = strFileName;
scripter.Options.DriAll = true;
scripter.Options.AppendToFile = true;
scripter.Script(list.ToArray());//Table Script completed
//Store Procedures scripting Writing
list = new List<SqlSmoObject>();
DataTable dataTable = dbUltimateSurvey.EnumObjects(DatabaseObjectTypes.StoredProcedure);
foreach (DataRow row in dataTable.Rows)
{
string sSchema = (string)row["Schema"];
if (sSchema == "sys" || sSchema == "INFORMATION_SCHEMA")
continue;
StoredProcedure sp = (StoredProcedure)databaseServer.GetSmoObject(
new Urn((string)row["Urn"]));
if (!sp.IsSystemObject)
if (sp.Name.Contains("custom_"))
list.Add(sp);
}
scripter.Server = databaseServer;
scripter.Options.IncludeHeaders = true;
scripter.Options.SchemaQualify = true;
scripter.Options.ToFileOnly = true;
scripter.Options.FileName = strFileName;
scripter.Options.DriAll = true;
scripter.Options.AppendToFile = true;
scripter.Script(list.ToArray()); // Stored procedure Script completed
}
Вы можете написать код С# для запуска следующего запроса в своей базе данных.
Select * from sys.procedures
Я думаю, это то, что вы действительно ищете:
select SPECIFIC_NAME,ROUTINE_DEFINITION from information_schema.routines
Там также много полезных столбцов...
begin
--select column_name from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='Products'
--Declare the Table variable
DECLARE @GeneratedStoredProcedures TABLE
(
Number INT IDENTITY(1,1), --Auto incrementing Identity column
name VARCHAR(300) --The string value
)
--Decalre a variable to remember the position of the current delimiter
DECLARE @CurrentDelimiterPositionVar INT
declare @sqlCode varchar(max)
--Decalre a variable to remember the number of rows in the table
DECLARE @Count INT
--Populate the TABLE variable using some logic
INSERT INTO @GeneratedStoredProcedures SELECT name FROM sys.procedures where name like 'procGen_%'
--Initialize the looper variable
SET @CurrentDelimiterPositionVar = 1
--Determine the number of rows in the Table
SELECT @Count=max(Number) from @GeneratedStoredProcedures
--A variable to hold the currently selected value from the table
DECLARE @CurrentValue varchar(300);
--Loop through until all row processing is done
WHILE @CurrentDelimiterPositionVar <= @Count
BEGIN
--Load current value from the Table
SELECT @CurrentValue = name FROM @GeneratedStoredProcedures WHERE Number = @CurrentDelimiterPositionVar
--Process the current value
--print @CurrentValue
set @sqlCode = 'drop procedure ' + @CurrentValue
print @sqlCode
--exec (@sqlCode)
--Increment loop counter
SET @CurrentDelimiterPositionVar = @CurrentDelimiterPositionVar + 1;
END
end
Если вы откроете банку рефлектора на sqlmetal.exe(автономная часть LINQ-to-SQL, которая генерирует код из базы данных), вы можете увидеть SQL-запросы, которые он использует, чтобы получить список всех сохраненных процедур и функций. SQL похож, но не идентичен, на тот, что указан в этом ответе.
Это SQL, который я только что проверил и использовал в MSSQL
SELECT NAME from SYS.PROCEDURES
order by name
Если вам нужно найти определенное имя или подстроку/текст
SELECT NAME from SYS.PROCEDURES
where name like '%<TEXT_TO_LOOK_FOR>%'
order by name
Замените именно это, например:
SELECT NAME from SYS.PROCEDURES
where name like '%CUSTOMER%'
order by name
И вызов
EXEC sp_HelpText SPNAME
для каждой хранимой процедуры вы получите набор записей с одной строкой текста в строке
Предполагая, что у вас есть объект SqlConnection
с именем sqlCon, самый простой способ - вызвать sqlCon.GetSchema( "Процедуры" )