PDA

View Full Version : ارسال نام جدول به صورت پارامتر



MNosouhi
دوشنبه 27 آذر 1385, 00:36 صبح
قبلا به من گفته بودن که در Stored procedure نمیشه نام جدول رو بصورت پارامتر فرستاد ، اما این رو در همین سایت دیدم:


کد:


CREATE Procedure usp_GenerateTrigger
@TableName sysname
AS
BEGIN
DECLARE @Body_G nvarchar(1000), @Body_I nvarchar(4000)
, @Body_U nvarchar(4000), @Body_D nvarchar(4000)
DECLARE @PreCond nvarchar(200), @EquCond nVarchar(1000), @InEquCond nvarchar(1000)
DECLARE @Cond_U nvarchar(1000), @Cond_D nvarchar(1000), @Keys nvarchar(900)
DECLARE @Table sysname, @Schema sysname
DECLARE @Column sysname, @DataType Sysname, @IsIdentity bit
SELECT @Table =PARSENAME(@TableName,1)
, @Schema=ISNULL(PARSENAME(@TableName, 2), CURRENT_USER), @IsIdentity=0

SELECT @Body_G='IF EXISTS (SELECT * FROM SysObjects '+char(13)
+ ' WHERE Type = ''TR'' AND id = Object_id('''+@Schema+'.insTR_Audit_'+ @Table+''')) '+char(13)
+ ' Drop Trigger '+@Schema+'.insTR_Audit_'+@Table+char(13)
+ ' IF EXISTS (SELECT * FROM SysObjects '+char(13)
+ ' WHERE Type = ''TR'' AND id = Object_id('''+@Schema+'.updelTR_Audit_' + @Table+''')) '+char(13)
+ ' Drop Trigger '+@Schema+'.updelTR_Audit_'+@Table+char(13)
+ ' IF EXISTS (SELECT * FROM SysObjects '+char(13)
+ ' WHERE Type = ''TR'' AND id = Object_id('''+@Schema+'.delTR_Audit_' + @Table + ''')) '+char(13)
+ ' Drop Trigger '+@Schema+'.delTR_Audit_'+@Table+char(13)

Select @Body_I ='', @Body_U ='', @Body_D ='',
@EquCOnd ='', @InEquCond ='', @PreCond='',
@Cond_U='', @Cond_D ='', @Keys =''

select @Body_I ='Create Trigger insTR_Audit_'+@Table +' ON '+ @TableName +'
For Insert
As
', @Body_U='Create Trigger updelTR_Audit_'+@Table +' ON '+@TableName+ '
For Update
As
', @Body_d='Create Trigger delTR_Audit_'+@Table+' ON '+@TableName+'
For Delete
As
'

Select @Keys= @Keys +', ['+ COL_Name(Object_ID(@TableName), k.COLID)+']'
from sysIndexKeys k, sysindexes I
Where i.id=object_ID(@TableName) and
i.id = k.id and i.indid=k.indid and
i.status & 0x800 =0x800
order by keyno
--Select @keys
IF LEN(@Keys)>1
select @Keys = SUBSTRING(@Keys, 3, LEN(@Keys)-2)
ELSE
BEGIN
PRINT 'No Primary Keys are available to handle the operation'
RETURN
END

IF CharIndex(', [', @Keys, 2)=0 --there is only one field now check whether it is identity
BEGIN
IF Exists(Select * from syscolumns where name =Substring(@Keys,2, LEn(@Keys)-2) and autoval is not null)
Set @IsIdentity=1
END


Declare FieldList Cursor FOR
Select COLUMN_NAME, DATA_TYPE from Information_Schema.Columns Where TABLE_Name =@Table and TABLE_SCHEMA=@Schema and Data_Type <> 'TimeStamp'
Open FieldList
FETCH NEXT FROM FieldList INTO @Column, @DataType
WHILE @@FETCH_STATUS=0
BEGIN

IF CHARINDEX(''+@Column+'', @Keys)>0
SELECT @Cond_U =@Cond_U+ '+'' AND ' +@Column +' = ''+'+
CASE
WHEN @DataType in ('Smalldatetime', 'DateTime') THEN '
''''''''+ Convert(Varchar(30), I.'+ @Column +', 113)+''''''''
'
WHEN @DataType in ('bigint','bit','BINARY', 'varbinary', 'int', 'smallint', 'tinyint', 'real', 'decimal', 'float', 'money', 'numeric') THEN
' Convert(Varchar(35), I.'+ @Column +')
'
ELSE
' ''''''''+I.'+ @Column + '+''''''''
'
END,
@EquCond = @EquCond+ ' AND I.'+ @Column +' = D.'+@Column,
@InEquCond = @InEquCond+ ' AND I.'+ @Column +' <> D.'+@Column,
@PreCond = @preCond+' AND Update('+ @Column+')',
@Cond_d =@Cond_d+ '+'' AND ' +@Column +' = ''+'+
CASE
WHEN @DataType in ('Smalldatetime', 'DateTime') THEN '
''''''''+ Convert(Varchar(30), D.'+ @Column +', 113)+''''''''
'
WHEN @DataType in ('bigint','bit','BINARY', 'varbinary', 'int', 'smallint', 'tinyint', 'real', 'decimal', 'float', 'money', 'numeric') THEN
' Convert(Varchar(35), D.'+ @Column +')
'
ELSE
' ''''''''+D.'+ @Column + '+''''''''
'
END
FETCH NEXT FROM FieldList INTO @Column, @DataType

END
CLOSE FieldList

deallocate FieldList
IF LEN(@Cond_D)>7
SELECT @Cond_D = ''''+SUBSTRING(@Cond_D, 8, LEN(@Cond_D )-7)
IF LEN(@Cond_U)>7
SELECT @Cond_U = ''''+SUBSTRING(@Cond_U, 8, LEN(@Cond_U )-7)
IF LEN(@PreCond)>5
SELECT @PreCond= 'IF '+ SUBSTRING(@PreCond, 6, LEN(@PreCond)-5)
IF LEN(@EquCond)>5
SELECT @EquCond= ' WHERE '+ SUBSTRING(@EquCond, 6, LEN(@EquCond)-5)
IF LEN(@InEquCond)>5
SELECT @InEquCond= 'WHERE '+ SUBSTRING(@InEquCond, 6, LEN(@InEquCond)-5)


select @Body_I = @Body_I + 'IF EXISTS (Select * from Inserted)
Insert into LogTable (LOG_Table, LOG_Condition, LOG_Action)
Select '''+@Table+''', '+@Cond_U+',''I'' from Inserted I
'
IF @IsIdentity=0
SELECT @Body_U =@Body_U + 'IF EXISTS (Select * from Inserted)
'+@PreCond +'
Insert into LogTable (LOG_Table, LOG_Condition, LOG_ConditionD, LOG_Action)
Select '''+@Table+''', '+@Cond_U+','+@Cond_D+',''U'' from Inserted I, Deleted D
'+@InEquCond+'
ELSE
Insert into LogTable (LOG_Table, LOG_Condition, LOG_ConditionD, LOG_Action)
Select '''+@Table+''', '+@Cond_U+','+@Cond_D+',''U'' from Inserted I, Deleted D
'+@EquCond
Else
SELECT @Body_U =@Body_U + 'Insert into LogTable (LOG_Table, LOG_Condition, LOG_ConditionD, LOG_Action)
Select '''+@Table+''', '+@Cond_U+','+@Cond_D+',''U'' from Inserted I, Deleted D
'+@EquCond

Select @Body_D = @Body_D+'IF EXISTS (Select * from Deleted)
Insert into LogTable (LOG_Table, LOG_ConditionD, LOG_Action)
Select '''+@Table+''', '+@Cond_D+',''D'' from Deleted D
'
Execute sp_ExecuteSQL @Body_G
Execute sp_ExecuteSQL @Body_I
Execute sp_ExecuteSQL @Body_U
Execute sp_ExecuteSQL @Body_D
ENDبعد رویه رو با نام یک جدول فراخوانی می کنید.

کد:
EXEC usp_GenerateTrigger 'stores'

حالا میشه یکی توضیح بده چطوری میشه نام جدول رو بصورت پارامتر فرستاد . هر چی روش کار کردم آخرش خطا میده.

Kamyar.Kimiyabeigi
دوشنبه 27 آذر 1385, 08:18 صبح
این یک مثال فوق العاده ساده


CREATE PROCEDURE Test @TblName NVARCHAR(100)
AS
EXECUTE('SELECT * FROM ' + @TblName)

h_baqery
دوشنبه 27 آذر 1385, 10:56 صبح
خطاهاش احتمالا به خاطر تعداد کوتیشنها (') هستش . در Execute هر جا که خود متن هم کوتیشن دارد باید از دو تا کوتیشن استفاده کنید تا execute متوجه شود که آخر متن نیست .

odiseh
دوشنبه 27 آذر 1385, 13:10 عصر
خطاهاش احتمالا به خاطر تعداد کوتیشنها (') هستش . در Execute هر جا که خود متن هم کوتیشن دارد باید از دو تا کوتیشن استفاده کنید تا execute متوجه شود که آخر متن نیست .

یعنی داخل یک string هر جا که می خواهیم یه کوتیشن قرار بدیم هر یه دونه رو دو تا درج کنیم و در نهایت کوتیشن آخر string رو هم بذاریم درسته؟

h_baqery
دوشنبه 27 آذر 1385, 14:02 عصر
بله درسته.

اینم توضیح BOL

If the value of a parameter is an object name, character string, or qualified by a database name or schema name, the whole name must be enclosed in single quotation marks. If the value of a parameter is a keyword, the keyword must be enclosed in double quotation marks.

MNosouhi
سه شنبه 28 آذر 1385, 10:58 صبح
از همه دوستان ممنون.
مثالی میخام که از دستور execute استفاده نکرده باشه.
ممکنه؟