查询所有存储过程
--查詢所有存儲過程
select Pr_Name as [存儲過程], [參數]=stuff((select ','+[Parameter]
??? from (
??????? select Pr.Name as Pr_Name,parameter.name +' ' +Type.Name + ' ('+convert(varchar(32),parameter.max_length)+')' as Parameter
??????? from sys.procedures Pr left join
??????? sys.parameters parameter on Pr.object_id = parameter.object_id
??????? inner join sys.types Type on parameter.system_type_id = Type.system_type_id
??????? where type = 'P'
??? ) t where Pr_Name=tb.Pr_Name for xml path('')), 1, 1, '')
from (
??? select Pr.Name as Pr_Name,parameter.name +' ' +Type.Name + ' ('+convert(varchar(32),parameter.max_length)+')' as Parameter
??? from sys.procedures Pr left join
??? sys.parameters parameter on Pr.object_id = parameter.object_id
??? inner join sys.types Type on parameter.system_type_id = Type.system_type_id
??? where type = 'P'
)tb
where Pr_Name not like 'sp_%' --and Pr_Name not like 'dt%'
group by Pr_Name
order by Pr_Name
--查詢所有觸發器
select triggers.name as [觸發器],tables.name as [表名],triggers.is_disabled as [是否禁用],
triggers.is_instead_of_trigger AS [觸發器類型],
case when triggers.is_instead_of_trigger = 1 then 'INSTEAD OF'
???? when triggers.is_instead_of_trigger = 0 then 'AFTER'
???? else null
end as [觸發器類型描述]
from sys.triggers triggers
inner join sys.tables tables on triggers.parent_id = tables.object_id
where triggers.type ='TR'
order by triggers.create_date
--查詢所有索引
select??? indexs.Tab_Name as [表名],indexs.Index_Name as [索引名] ,indexs.[Co_Names] as [索引列],
??????? Ind_Attribute.is_primary_key as [是否主鍵],Ind_Attribute.is_unique AS [是否唯一鍵],
??????? Ind_Attribute.is_disabled AS [是否禁用]
from (
??? select Tab_Name,Index_Name, [Co_Names]=stuff((select ','+[Co_Name] from
??? (??? select tab.Name as Tab_Name,ind.Name as Index_Name,Col.Name as Co_Name from sys.indexes ind
??????? inner join sys.tables tab on ind.Object_id = tab.object_id and ind.type in (1,2)/*索引的類型:0=堆/1=聚集/2=非聚集/3=XML*/
??????? inner join sys.index_columns index_columns on tab.object_id = index_columns.object_id and ind.index_id = index_columns.index_id
??????? inner join sys.columns Col on tab.object_id = Col.object_id and index_columns.column_id = Col.column_id
??? ) t where Tab_Name=tb.Tab_Name and Index_Name=tb.Index_Name for xml path('')), 1, 1, '')
??? from (
??????? select tab.Name as Tab_Name,ind.Name as Index_Name,Col.Name as Co_Name from sys.indexes ind
??????? inner join sys.tables tab on ind.Object_id = tab.object_id and ind.type in (1,2)/*索引的類型:0=堆/1=聚集/2=非聚集/3=XML*/
??????? inner join sys.index_columns index_columns on tab.object_id = index_columns.object_id and ind.index_id = index_columns.index_id
??????? inner join sys.columns Col on tab.object_id = Col.object_id and index_columns.column_id = Col.column_id
??? )tb
??? where Tab_Name not like 'sys%'
??? group by Tab_Name,Index_Name
) indexs inner join sys.indexes Ind_Attribute on indexs.Index_Name = Ind_Attribute.name
order by indexs.Tab_Name
DECLARE @s VARCHAR(4000),@n INT,@i INT,@s1 VARCHAR(100)
SELECT IDENTITY(INT) id,text INTO ##
??? FROM syscomments
SELECT @n=@@ROWCOUNT,@i=0
WHILE @i<@n
??? BEGIN
??????? SELECT @i=@i+1,@s=''
??????? SELECT @s1=REPLACE(REPLACE(RTRIM(LTRIM(STUFF(STUFF(text,CHARINDEX('AS',text),40000,''),1,
?????????????????????????????? CHARINDEX('PROC',STUFF(text,CHARINDEX('AS',text),40000,''))+4,''))),CHAR(10),''),CHAR(13),'')
??????????? FROM ## WHERE ID=RTRIM(@i)
??????????? --SELECT @s1,ASCII(SUBSTRING(@s1,3,1))
??????????? --SELECT LEN(REPLACE(REPLACE(@s1,CHAR(13),''),CHAR(10),''))
??????? SELECT @s='SELECT text FROM tempdb.dbo.## WHERE ID=' + RTRIM(@i)
??????? EXEC('EXEC master..xp_cmdshell ''bcp "' + @s + ' "? queryout "e:\ProcTXT\' + @s1 + '.txt" -S"ROBINHOME\SQLEXPRESS" -c -U"sa" -P"bd5178"''')
??? END
DROP TABLE ##
--自己寫的 如何識別換行??? 還有些非存儲過程的對象
SELECT top 10 text FROM syscomments where id in(
select object_id from sys.procedures where type = 'P')
SELECT text FROM syscomments where id in(
select object_id from sys.procedures where type = 'P')
and charindex('ALLSTOCK',text)>0
and charindex('CREATE PROCEDURE',text)>0
在一個應用系統中,如果編寫了大量的Sybase存儲過程,對存儲過程進行系統、有效地備份是必須的。而我們通常用的辦法是使用Sybase提供的 Sybase Central工具先選定存儲過程,然后通過鼠標右鍵選擇Generate DDL的方式把存儲過程備份下來。使用這種方式,不僅備份時間特別長(備份文件為6M左右時,達幾個小時之久),更要命的是使用該方式備份下來的存儲過程文本往往無法直接使用,因為在每個存儲過程體后自動加的關鍵字go,有時就直接放在過程體最后一行尾部,沒有空格,這樣要使用該文本重新建過程時,需要花大量的時間進行修正。因此,找一種備份速度既快備份后內容又規整的方法來替代該工具是完全有必要的。
筆者在實際工作中,交*使用以下兩種方法,對存儲過程進行備份。方法一:通過編寫嵌入sql的C程序,實現整庫存儲過程的快速導出。方法二:通過defncopy快速導出指定的存儲過程。現分別詳細介紹如下:
[b]方法一:通過cpre實現快速導出[/b]
以下程序通過sybase的cpre預編譯處理生成可執行文件后,可以實現存儲過程的快速導出,在數據庫空閑時,可以在一分鐘之內導出所有的存儲過程(生成的文件有6M左右,而Sybase Central需要以小時計)。
該程序運行時格式如下(設可執行文件為exportproc):
sybase> exprotproc 文件名
執行完后,所有的存儲過程體就存放在該文件中,文件的內容也保存了存儲過程的書寫格式,并在每個存儲過程后面加一個單獨的行go。為了使程序靈活,在正式導之前根據提示需要輸入用戶名、口令、聯機串、數據庫名。
#include
#include
EXEC SQL INCLUDE SQLCA;
void Sql_Error();
main( argc, argv)
int argc;
char **argv;
{
FILE *fp;
char useName[11], usePasswd[11], dbString[16];
char *fpass;
long oldId;
EXEC SQL BEGIN DECLARE SECTION;
char textLine[256];
long id;
char dbName[20];
EXEC SQL END DECLARE SECTION;
/*輸入參數不夠,給出使用提示*/
if (argc!=2){
printf("Usage As %s \n", argv[0]);
exit(0);
}
if( (fp=fopen(argv[1],"w+"))==NULL){
printf("Open file %s error\n",argv[1]);
exit(0);
}
/*輸入聯庫用戶名*/
printf("Please Input user name:");
gets(useName);
/*輸入用戶口令,在輸入時屏幕不顯示輸入內容*/
fpass=getpass("Please Input Passwd:");
strcpy(usePasswd,fpass);
/*輸入聯庫字符串*/
printf("Please Input Database string:");
gets(dbString);
/*輸入要導出其中存儲過程的庫名*/
printf("Please Input Database Name:");
gets(dbName);
EXEC SQL WHENEVER SQLERROR CALL Sql_Error();
if( ConnectDB(useName, usePasswd, dbString) !=0){ /*連接數據庫*/
printf("Can't connect database\n");
exit(0);
}
else
printf("Connect database ok!\n");
printf("Begin to export PROCEDURE Please wait...\n");
EXEC SQL use :dbName;
EXEC SQL commit;
/*聲明游標,找出該庫中所有的存儲過程對應的內容*/
EXEC SQL declare pro_cur cursor for
SELECT id, text from syscomments
where id in (select id from sysobjects
where type = 'P')
and texttype=0
and text is not null
order by id, number,colid2,colid;
EXEC SQL OPEN pro_cur;
EXEC SQL FETCH pro_cur into :id, :textLine;
oldId=-9999L;
while(!sqlca.sqlcode){
/*當一個存儲過程結束后,在其過程體后加入新行GO*/
fprintf(fp,"\nGO\n\n");
}
oldId=id;
fprintf(fp,"%s",textLine);
EXEC SQL FETCH pro_cur INTO :id, :textLine;
}
EXEC SQL CLOSE pro_cur;
fprintf(fp,"\nGO\n\n");
fclose(fp);
printf("End export PROCEDURE !\n");
/*斷開于數據庫的連接*/
DisConnectDB();
printf("Disconnect DataBase success!\n");
}
void Sql_Error()
{
EXEC SQL WHENEVER SQLERROR CONTINUE;
printf("Error.\n");
printf("%s\n",sqlca.sqlerrm.sqlerrmc);
exit(0);
}
/*連接數據庫函數*/
int ConnectDB( username, password, dbstring)
EXEC SQL BEGIN DECLARE SECTION;
CS_CHAR *username,*password,*dbstring;
EXEC SQL END DECLARE SECTION;
{
EXEC SQL SET CHAINED OFF;
EXEC SQL CONNECT :username IDENTIFIED BY :password USING :dbstring;
return(sqlca.sqlcode);
}
/*斷開數據庫函數*/
int DisConnectDB()
{
EXEC SQL DISCONNECT ALL;
return 0;
}
該程序在IBM AIX4.3、hp-unix 11.0、tru64 unix5.0平臺上測試通過。
[b]方法二:通過defncopy實現快速導出[/b]
在需要對一些存儲過程單獨進行備份時,往往使用defncopy通過拼串的方式進行。具體步驟如下:
1.根據需要備份的存儲過程,先編寫此crtprocout.sql文件,假設導出所有以PR_JF開頭的存儲過程,內容如下:
select "defncopy -U用戶名 -P口令 -S聯機串名 out "+name+".sql 庫名 "+name from sysobjects where type='P' and name like "PR_JF%"
2.利用上述文件,生成導過程腳本
isql -U用戶名 -P口令 -S聯機串名 –I crtprocout.sql –o procout
3.改變文件procout的權限
chmod +x procout
4.執行腳本導出過程,每個過程腳本名為:過程名+后綴”.sql”
./procout
小結:以上兩種辦法通過修改sql語句里的where條件相互之間是可以代替的。但筆者認為,前者適合對整庫的過程進行備份,而后者適合對指定的幾個過程進行備份。因為前者會對所有的過程腳本生成到一個文件里,適合面向多個過程的管理和備份;而后者一個過程腳本生成一個文件,適合面向單個過程的管理和備份。以上兩種方法通過簡單修改也可進行觸發器等的導出。
select Pr_Name as [存儲過程], [參數]=stuff((select ','+[Parameter]
??? from (
??????? select Pr.Name as Pr_Name,parameter.name +' ' +Type.Name + ' ('+convert(varchar(32),parameter.max_length)+')' as Parameter
??????? from sys.procedures Pr left join
??????? sys.parameters parameter on Pr.object_id = parameter.object_id
??????? inner join sys.types Type on parameter.system_type_id = Type.system_type_id
??????? where type = 'P'
??? ) t where Pr_Name=tb.Pr_Name for xml path('')), 1, 1, '')
from (
??? select Pr.Name as Pr_Name,parameter.name +' ' +Type.Name + ' ('+convert(varchar(32),parameter.max_length)+')' as Parameter
??? from sys.procedures Pr left join
??? sys.parameters parameter on Pr.object_id = parameter.object_id
??? inner join sys.types Type on parameter.system_type_id = Type.system_type_id
??? where type = 'P'
)tb
where Pr_Name not like 'sp_%' --and Pr_Name not like 'dt%'
group by Pr_Name
order by Pr_Name
--查詢所有觸發器
select triggers.name as [觸發器],tables.name as [表名],triggers.is_disabled as [是否禁用],
triggers.is_instead_of_trigger AS [觸發器類型],
case when triggers.is_instead_of_trigger = 1 then 'INSTEAD OF'
???? when triggers.is_instead_of_trigger = 0 then 'AFTER'
???? else null
end as [觸發器類型描述]
from sys.triggers triggers
inner join sys.tables tables on triggers.parent_id = tables.object_id
where triggers.type ='TR'
order by triggers.create_date
--查詢所有索引
select??? indexs.Tab_Name as [表名],indexs.Index_Name as [索引名] ,indexs.[Co_Names] as [索引列],
??????? Ind_Attribute.is_primary_key as [是否主鍵],Ind_Attribute.is_unique AS [是否唯一鍵],
??????? Ind_Attribute.is_disabled AS [是否禁用]
from (
??? select Tab_Name,Index_Name, [Co_Names]=stuff((select ','+[Co_Name] from
??? (??? select tab.Name as Tab_Name,ind.Name as Index_Name,Col.Name as Co_Name from sys.indexes ind
??????? inner join sys.tables tab on ind.Object_id = tab.object_id and ind.type in (1,2)/*索引的類型:0=堆/1=聚集/2=非聚集/3=XML*/
??????? inner join sys.index_columns index_columns on tab.object_id = index_columns.object_id and ind.index_id = index_columns.index_id
??????? inner join sys.columns Col on tab.object_id = Col.object_id and index_columns.column_id = Col.column_id
??? ) t where Tab_Name=tb.Tab_Name and Index_Name=tb.Index_Name for xml path('')), 1, 1, '')
??? from (
??????? select tab.Name as Tab_Name,ind.Name as Index_Name,Col.Name as Co_Name from sys.indexes ind
??????? inner join sys.tables tab on ind.Object_id = tab.object_id and ind.type in (1,2)/*索引的類型:0=堆/1=聚集/2=非聚集/3=XML*/
??????? inner join sys.index_columns index_columns on tab.object_id = index_columns.object_id and ind.index_id = index_columns.index_id
??????? inner join sys.columns Col on tab.object_id = Col.object_id and index_columns.column_id = Col.column_id
??? )tb
??? where Tab_Name not like 'sys%'
??? group by Tab_Name,Index_Name
) indexs inner join sys.indexes Ind_Attribute on indexs.Index_Name = Ind_Attribute.name
order by indexs.Tab_Name
DECLARE @s VARCHAR(4000),@n INT,@i INT,@s1 VARCHAR(100)
SELECT IDENTITY(INT) id,text INTO ##
??? FROM syscomments
SELECT @n=@@ROWCOUNT,@i=0
WHILE @i<@n
??? BEGIN
??????? SELECT @i=@i+1,@s=''
??????? SELECT @s1=REPLACE(REPLACE(RTRIM(LTRIM(STUFF(STUFF(text,CHARINDEX('AS',text),40000,''),1,
?????????????????????????????? CHARINDEX('PROC',STUFF(text,CHARINDEX('AS',text),40000,''))+4,''))),CHAR(10),''),CHAR(13),'')
??????????? FROM ## WHERE ID=RTRIM(@i)
??????????? --SELECT @s1,ASCII(SUBSTRING(@s1,3,1))
??????????? --SELECT LEN(REPLACE(REPLACE(@s1,CHAR(13),''),CHAR(10),''))
??????? SELECT @s='SELECT text FROM tempdb.dbo.## WHERE ID=' + RTRIM(@i)
??????? EXEC('EXEC master..xp_cmdshell ''bcp "' + @s + ' "? queryout "e:\ProcTXT\' + @s1 + '.txt" -S"ROBINHOME\SQLEXPRESS" -c -U"sa" -P"bd5178"''')
??? END
DROP TABLE ##
--自己寫的 如何識別換行??? 還有些非存儲過程的對象
SELECT top 10 text FROM syscomments where id in(
select object_id from sys.procedures where type = 'P')
SELECT text FROM syscomments where id in(
select object_id from sys.procedures where type = 'P')
and charindex('ALLSTOCK',text)>0
and charindex('CREATE PROCEDURE',text)>0
在一個應用系統中,如果編寫了大量的Sybase存儲過程,對存儲過程進行系統、有效地備份是必須的。而我們通常用的辦法是使用Sybase提供的 Sybase Central工具先選定存儲過程,然后通過鼠標右鍵選擇Generate DDL的方式把存儲過程備份下來。使用這種方式,不僅備份時間特別長(備份文件為6M左右時,達幾個小時之久),更要命的是使用該方式備份下來的存儲過程文本往往無法直接使用,因為在每個存儲過程體后自動加的關鍵字go,有時就直接放在過程體最后一行尾部,沒有空格,這樣要使用該文本重新建過程時,需要花大量的時間進行修正。因此,找一種備份速度既快備份后內容又規整的方法來替代該工具是完全有必要的。
筆者在實際工作中,交*使用以下兩種方法,對存儲過程進行備份。方法一:通過編寫嵌入sql的C程序,實現整庫存儲過程的快速導出。方法二:通過defncopy快速導出指定的存儲過程。現分別詳細介紹如下:
[b]方法一:通過cpre實現快速導出[/b]
以下程序通過sybase的cpre預編譯處理生成可執行文件后,可以實現存儲過程的快速導出,在數據庫空閑時,可以在一分鐘之內導出所有的存儲過程(生成的文件有6M左右,而Sybase Central需要以小時計)。
該程序運行時格式如下(設可執行文件為exportproc):
sybase> exprotproc 文件名
執行完后,所有的存儲過程體就存放在該文件中,文件的內容也保存了存儲過程的書寫格式,并在每個存儲過程后面加一個單獨的行go。為了使程序靈活,在正式導之前根據提示需要輸入用戶名、口令、聯機串、數據庫名。
#include
#include
EXEC SQL INCLUDE SQLCA;
void Sql_Error();
main( argc, argv)
int argc;
char **argv;
{
FILE *fp;
char useName[11], usePasswd[11], dbString[16];
char *fpass;
long oldId;
EXEC SQL BEGIN DECLARE SECTION;
char textLine[256];
long id;
char dbName[20];
EXEC SQL END DECLARE SECTION;
/*輸入參數不夠,給出使用提示*/
if (argc!=2){
printf("Usage As %s \n", argv[0]);
exit(0);
}
if( (fp=fopen(argv[1],"w+"))==NULL){
printf("Open file %s error\n",argv[1]);
exit(0);
}
/*輸入聯庫用戶名*/
printf("Please Input user name:");
gets(useName);
/*輸入用戶口令,在輸入時屏幕不顯示輸入內容*/
fpass=getpass("Please Input Passwd:");
strcpy(usePasswd,fpass);
/*輸入聯庫字符串*/
printf("Please Input Database string:");
gets(dbString);
/*輸入要導出其中存儲過程的庫名*/
printf("Please Input Database Name:");
gets(dbName);
EXEC SQL WHENEVER SQLERROR CALL Sql_Error();
if( ConnectDB(useName, usePasswd, dbString) !=0){ /*連接數據庫*/
printf("Can't connect database\n");
exit(0);
}
else
printf("Connect database ok!\n");
printf("Begin to export PROCEDURE Please wait...\n");
EXEC SQL use :dbName;
EXEC SQL commit;
/*聲明游標,找出該庫中所有的存儲過程對應的內容*/
EXEC SQL declare pro_cur cursor for
SELECT id, text from syscomments
where id in (select id from sysobjects
where type = 'P')
and texttype=0
and text is not null
order by id, number,colid2,colid;
EXEC SQL OPEN pro_cur;
EXEC SQL FETCH pro_cur into :id, :textLine;
oldId=-9999L;
while(!sqlca.sqlcode){
/*當一個存儲過程結束后,在其過程體后加入新行GO*/
fprintf(fp,"\nGO\n\n");
}
oldId=id;
fprintf(fp,"%s",textLine);
EXEC SQL FETCH pro_cur INTO :id, :textLine;
}
EXEC SQL CLOSE pro_cur;
fprintf(fp,"\nGO\n\n");
fclose(fp);
printf("End export PROCEDURE !\n");
/*斷開于數據庫的連接*/
DisConnectDB();
printf("Disconnect DataBase success!\n");
}
void Sql_Error()
{
EXEC SQL WHENEVER SQLERROR CONTINUE;
printf("Error.\n");
printf("%s\n",sqlca.sqlerrm.sqlerrmc);
exit(0);
}
/*連接數據庫函數*/
int ConnectDB( username, password, dbstring)
EXEC SQL BEGIN DECLARE SECTION;
CS_CHAR *username,*password,*dbstring;
EXEC SQL END DECLARE SECTION;
{
EXEC SQL SET CHAINED OFF;
EXEC SQL CONNECT :username IDENTIFIED BY :password USING :dbstring;
return(sqlca.sqlcode);
}
/*斷開數據庫函數*/
int DisConnectDB()
{
EXEC SQL DISCONNECT ALL;
return 0;
}
該程序在IBM AIX4.3、hp-unix 11.0、tru64 unix5.0平臺上測試通過。
[b]方法二:通過defncopy實現快速導出[/b]
在需要對一些存儲過程單獨進行備份時,往往使用defncopy通過拼串的方式進行。具體步驟如下:
1.根據需要備份的存儲過程,先編寫此crtprocout.sql文件,假設導出所有以PR_JF開頭的存儲過程,內容如下:
select "defncopy -U用戶名 -P口令 -S聯機串名 out "+name+".sql 庫名 "+name from sysobjects where type='P' and name like "PR_JF%"
2.利用上述文件,生成導過程腳本
isql -U用戶名 -P口令 -S聯機串名 –I crtprocout.sql –o procout
3.改變文件procout的權限
chmod +x procout
4.執行腳本導出過程,每個過程腳本名為:過程名+后綴”.sql”
./procout
小結:以上兩種辦法通過修改sql語句里的where條件相互之間是可以代替的。但筆者認為,前者適合對整庫的過程進行備份,而后者適合對指定的幾個過程進行備份。因為前者會對所有的過程腳本生成到一個文件里,適合面向多個過程的管理和備份;而后者一個過程腳本生成一個文件,適合面向單個過程的管理和備份。以上兩種方法通過簡單修改也可進行觸發器等的導出。
轉載于:https://www.cnblogs.com/zhuawang/archive/2011/08/22/2148801.html
總結
- 上一篇: “关关鸣鸟列”上一句是什么
- 下一篇: 缅怀过去