创建_Log表及触发器

SQL Server “复制”表结构,创建_Log表及触发器

实例效果:

贯彻表数据的增修删时,记录日志。

创建_Log表及触发器。1.“复制”现有表,

   创设相应的_Log表;

 (注意点:

通过select union all 的方式,避免了IDENTITY 的“复制”,
即如果原表有 PK 如 ID Identity,_Log表 仅“复制”ID int,“不复制” Identity属性,
以便 Insert Update Delete时,可以Insert到Log表。)

2.对现有表,创制Insert,Update,Delete的触发器,

  并将相应数据 记录到对应的_Log表

BEGIN TRAN   
BEGIN TRY  


--定义TAB_CURSOR
DECLARE TAB_CURSOR CURSOR read_only
FOR
   SELECT name FROM SysObjects Where XType='U' 
  -- AND name = N'T01ConstItem' 
  and [name] <> N'dtproperties'
   ORDER BY Name;

--打开
OPEN TAB_CURSOR

DECLARE @P_TabName NVARCHAR(200);
DECLARE @P_TabName_Log NVARCHAR(200);
DECLARE @P_Create_Log_Tab NVARCHAR(4000);
DECLARE @P_Create_Trig_I NVARCHAR(4000);
DECLARE @P_Create_Trig_U NVARCHAR(4000);
DECLARE @P_Create_Trig_D NVARCHAR(4000);

FETCH NEXT FROM TAB_CURSOR 
           INTO @P_TabName
--循环
WHILE (@@FETCH_STATUS <> -1)
BEGIN
   IF (@@FETCH_STATUS <> -2)
    BEGIN   
    SET @P_TabName_Log = CONCAT(@P_TabName,N'_Log');

    SET @P_Create_Log_Tab = N' SELECT * ';
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' ,N''I '' AS Action');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' ,Getdate() AS ActionDate ');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' INTO ');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,@P_TabName_Log );
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' FROM  ' );
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,@P_TabName);
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' UNION ALL ');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' SELECT TOP (1) * ');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' ,N''I '' AS Action');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' ,Getdate() AS ActionDate ');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' FROM  ' );
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,@P_TabName);
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab, N' WHERE 1=0 ; ');

    EXEC( @P_Create_Log_Tab);

    --SET @P_Create_Log_Tab = CONCAT(N' SET IDENTITY_INSERT ',@P_TabName_Log ,' ON '); 
    --EXEC( @P_Create_Log_Tab);


    SET @P_Create_Trig_I = N' create trigger ';
    SET @P_Create_Trig_I = CONCAT(@P_Create_Trig_I,N' trig_',@P_TabName,N'_I ');
    SET @P_Create_Trig_I = CONCAT(@P_Create_Trig_I,N' on ',@P_TabName,N' after INSERT as ');
    SET @P_Create_Trig_I = CONCAT(@P_Create_Trig_I, N' begin ');    
    SET @P_Create_Trig_I = CONCAT(@P_Create_Trig_I, N'insert into ',@P_TabName_Log );
    SET @P_Create_Trig_I = CONCAT(@P_Create_Trig_I,N' select * , N''I'',Getdate() from Inserted ; ' );
    SET @P_Create_Trig_I = CONCAT(@P_Create_Trig_I, N'end ');

    --select @P_Create_Trig_I;

    EXEC( @P_Create_Trig_I);

    SET @P_Create_Trig_U = N' create trigger ';
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' trig_',@P_TabName,N'_U ');
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' on ',@P_TabName,N' after UPDATE as ');
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N' begin ');
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N'insert into ',@P_TabName_Log );
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' select * , N''UD'',Getdate() from Deleted ; ' );
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N'insert into ',@P_TabName_Log );
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' select * , N''UI'',Getdate() from Inserted ; ' );
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N'end ');
    EXEC( @P_Create_Trig_U);

    SET @P_Create_Trig_U = N' create trigger ';
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' trig_',@P_TabName,N'_D ');
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' on ',@P_TabName,N' after DELETE as ');
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N' begin ');
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N'insert into ',@P_TabName_Log );
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' select * , N''D'',Getdate() from Deleted ; ' );
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N'end ');
    EXEC( @P_Create_Trig_U);

    END
   FETCH NEXT FROM TAB_CURSOR INTO @P_TabName
END

--关闭
CLOSE TAB_CURSOR
--释放
DEALLOCATE TAB_CURSOR

COMMIT TRAN;  

END TRY  
BEGIN CATCH  
    SELECT ERROR_MESSAGE() AS ErrorMessage  
    ,ERROR_SEVERITY() AS ErrorSeverity  
    ,ERROR_STATE() AS ErrorState  
    ROLLBACK TRAN;  
END CATCH

 

转发来源于:

实例效果:

  不知不觉讲到触发器了,一般大家做程序的很少接触到触发器,触发器的操作一般是DB人士来完毕。

我们那边介绍多个独特的表,Inserted表和Deleted表。此二表仅仅在触发器运行时存在。你可以行使该七个表来精确地规定触发触发器的动作对数据表所做的修改。比如,通过检查Deleted表,你可以规定那多少个记录由某一动作删除。考虑上边的事例:

心想事成表数据的增修删时,记录日志。

  然则有的时候有些简便的作业要求大家和好去达成,不可能每趟都去麻烦DB人员,所以说,编程人士要全才,除了编程以为的专业知识也要读书,比如js,css,html,t-sql等局地语法,不必然要去精通,然则要熟知,至少语法可以看懂,那样对大家的编程有经济的功用,出现很是错误,大家也便宜调试,以便最快找出错误。

CREATE TRIGGER tr_webusers_delete ON webusers

1.“复制”现有表,

  言归正传,什么事触发器,顾名思义,就是你做一个操作,就会触发另一个事件,去履行一些操作。

FOR DELETE

   创造相应的_Log表;

  比如你点烟花,点是一个动作,烟花是另一个动作,点动作形成就会触发烟花这些动作。

AS

 (注意点:

  还有就是触发器必须依附一个要旨,比如依附于某一张表,如同编程中事件那么些定义。

INSERT weblog (activity) SELECT user_name FROM Deleted

通过select union all 的方式,避免了IDENTITY 的“复制”,
即如果原表有 PK 如 ID Identity,_Log表 仅“复制”ID int,“不复制” Identity属性,
以便 Insert Update Delete时,可以Insert到Log表。)

  上面大家经过一个简约的实例,和大家一步一步的来了然和选取触发器。

该触发器自动地创造一个webusers表的笔录。当在webusers表内去除一个用户的全名时,触发器会活动地把该姓名插入到weblog表中。假使你一不小心执行了上面的口舌:

2.对现有表,创设Insert,Update,Delete的触发器,

  实例必要:

DELETE webusers

  并将相应数据 记录到对应的_Log表

    1,建商品表(Store),订单表(orders),日志表(Logs)

该语句会删除在webusers表内的具备记录。一般地,那几个记录会永久地丢失,可是下面的触发器会在有记录从webusers表中剔除时自动的触发。该触发器会检查表Deleted来规定有这一个在webusers表内的笔录被剔除,并且把持有删除了的笔录拷贝到weblog表中。

 

    2,创制订单表插入触发器,完毕插入一条订单信息,商品表中货物数量相应减弱,订单中的总金额相应扩充。

为了还原那个意外被剔除的记录,你能够采用INSERT和SELECT语句再度把它们从weblog表中拷贝到webusers表中。假如您不可以容许意外地丢失一条记下时,你可以选取方面的不二法门来创制一个表内数据的备份。

对应代码如下:

    3,创设订单表更新触发器,完成立异一条订单音讯,商品表中货物数量相应变更,订单中的总金额相应变更。(和2类似)

Deleted表和有记录被删除的表的列结构一模一样。在前方的例子内,Deleted表具有和webusers表相同的布局。

BEGIN TRAN   
BEGIN TRY  


--定义TAB_CURSOR
DECLARE TAB_CURSOR CURSOR read_only
FOR
   SELECT name FROM SysObjects Where XType='U' 
  -- AND name = N'T01ConstItem' 
  and [name] <> N'dtproperties'
   ORDER BY Name;

--打开
OPEN TAB_CURSOR

DECLARE @P_TabName NVARCHAR(200);
DECLARE @P_TabName_Log NVARCHAR(200);
DECLARE @P_Create_Log_Tab NVARCHAR(4000);
DECLARE @P_Create_Trig_I NVARCHAR(4000);
DECLARE @P_Create_Trig_U NVARCHAR(4000);
DECLARE @P_Create_Trig_D NVARCHAR(4000);

FETCH NEXT FROM TAB_CURSOR 
           INTO @P_TabName
--循环
WHILE (@@FETCH_STATUS <> -1)
BEGIN
   IF (@@FETCH_STATUS <> -2)
    BEGIN   
    SET @P_TabName_Log = CONCAT(@P_TabName,N'_Log');

    SET @P_Create_Log_Tab = N' SELECT * ';
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' ,N''I '' AS Action');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' ,Getdate() AS ActionDate ');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' INTO ');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,@P_TabName_Log );
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' FROM  ' );
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,@P_TabName);
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' UNION ALL ');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' SELECT TOP (1) * ');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' ,N''I '' AS Action');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' ,Getdate() AS ActionDate ');
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,N' FROM  ' );
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab,@P_TabName);
    SET @P_Create_Log_Tab = CONCAT(@P_Create_Log_Tab, N' WHERE 1=0 ; ');

    EXEC( @P_Create_Log_Tab);

    --SET @P_Create_Log_Tab = CONCAT(N' SET IDENTITY_INSERT ',@P_TabName_Log ,' ON '); 
    --EXEC( @P_Create_Log_Tab);


    SET @P_Create_Trig_I = N' create trigger ';
    SET @P_Create_Trig_I = CONCAT(@P_Create_Trig_I,N' trig_',@P_TabName,N'_I ');
    SET @P_Create_Trig_I = CONCAT(@P_Create_Trig_I,N' on ',@P_TabName,N' after INSERT as ');
    SET @P_Create_Trig_I = CONCAT(@P_Create_Trig_I, N' begin ');    
    SET @P_Create_Trig_I = CONCAT(@P_Create_Trig_I, N'insert into ',@P_TabName_Log );
    SET @P_Create_Trig_I = CONCAT(@P_Create_Trig_I,N' select * , N''I'',Getdate() from Inserted ; ' );
    SET @P_Create_Trig_I = CONCAT(@P_Create_Trig_I, N'end ');

    --select @P_Create_Trig_I;

    EXEC( @P_Create_Trig_I);

    SET @P_Create_Trig_U = N' create trigger ';
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' trig_',@P_TabName,N'_U ');
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' on ',@P_TabName,N' after UPDATE as ');
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N' begin ');
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N'insert into ',@P_TabName_Log );
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' select * , N''UD'',Getdate() from Deleted ; ' );
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N'insert into ',@P_TabName_Log );
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' select * , N''UI'',Getdate() from Inserted ; ' );
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N'end ');
    EXEC( @P_Create_Trig_U);

    SET @P_Create_Trig_U = N' create trigger ';
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' trig_',@P_TabName,N'_D ');
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' on ',@P_TabName,N' after DELETE as ');
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N' begin ');
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N'insert into ',@P_TabName_Log );
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U,N' select * , N''D'',Getdate() from Deleted ; ' );
    SET @P_Create_Trig_U = CONCAT(@P_Create_Trig_U, N'end ');
    EXEC( @P_Create_Trig_U);

    END
   FETCH NEXT FROM TAB_CURSOR INTO @P_TabName
END

--关闭
CLOSE TAB_CURSOR
--释放
DEALLOCATE TAB_CURSOR

COMMIT TRAN;  

END TRY  
BEGIN CATCH  
    SELECT ERROR_MESSAGE() AS ErrorMessage  
    ,ERROR_SEVERITY() AS ErrorSeverity  
    ,ERROR_STATE() AS ErrorState  
    ROLLBACK TRAN;  
END CATCH  

    4,创设日志表触发器,已毕立异商品表价格变化情形。

现在倘若你想跟踪所有插入某一报表的记录。比如,你想把每一条插入webusers表内的笔录都在weblog表内做备份,你可以使用下边的触发器来成功该任务:

 

1,创制商品表(Store),订单表(orders),日志表(Logs)

  第一步没怎么讲解,大家成立表,并加一些示范数据。

  示例代码:

 1 create table Store
 2 (
 3     ID uniqueidentifier primary key,
 4     ProductID int not null,
 5     ProductPrice money not null default 1,
 6     ProductCH nvarchar(80) not null,
 7     ProductDate datetime not null,
 8     NowNumber int not null
 9 );
10 create table orders
11 (
12     OrderID int primary key,
13     ProductID int not null,
14     BuyNumber int Not null default 1,
15     BuyPricr money not null,
16     NowOrderPrice money default 0 
17 )
18 create table Logs
19 (
20     ID uniqueidentifier primary key,
21     operatedatetime datetime,
22     ProductID int,
23     oldprice money,
24     newprice money
25 );
26 
27 insert into dbo.Store
28 values(NEWID(),1001,5000,'联想','2011-9-1',50)
29 insert into dbo.Store
30 values(NEWID(),1002,6000,'apple','2011-9-1',50)
31 insert into dbo.orders(OrderID,ProductID,BuyNumber,BuyPricr)
32 values(10013,1001,5,6000)

CREATE TRIGGER tr_webusers_insert ON webusers

2,创立订单表触发器

  要求2,3好像操作自己在联合讲解了。

  先看示例代码:

 1 create trigger tri_order_NowOrderPrice
 2 on orders after insert
 3 as
 4 begin
 5     declare @NowOrderPrice money;
 6     declare @BuyNumber int;
 7     declare @ProductID int;
 8     select @ProductID= ProductID,@BuyNumber= BuyNumber from inserted;
 9     select @NowOrderPrice=inserted.BuyNumber * inserted.BuyPricr from inserted;
10     update orders set NowOrderPrice=@NowOrderPrice where ProductID=@ProductID;
11     update Store set NowNumber=NowNumber-@BuyNumber where ProductID=@ProductID;
12 end;
13 
14 create trigger tri_store_NowOrderPrice2
15 on orders after update
16 as
17 begin
18     declare @NowOrderPrice money;
19     declare @ProductID int;
20     declare @BuyNumber1 int;
21     declare @BuyNumber2 int;
22     select @ProductID= ProductID from inserted;
23     select @BuyNumber1=BuyNumber from inserted;
24     select @NowOrderPrice=inserted.BuyNumber * inserted.BuyPricr from inserted;
25     select @BuyNumber2=deleted.BuyNumber from deleted where ProductID=@ProductID;
26     update orders set NowOrderPrice=@NowOrderPrice where ProductID=@ProductID;
27     update Store set NowNumber=NowNumber-(@BuyNumber1-@BuyNumber2) where ProductID=@ProductID;
28 end;

  触发器的最首要字是trigger,语法是,on
表名 after 操作名称(一般为insert,update,delete),begin
end中写一些触发器的处理操作。

  inserted得到insert之后的数量。语法就是这么不难。

FOR INSERT

3,创造日志表触发器

  日志表触发器要做的操作就是记录商品价位浮动,那对应就应有在商品表中创设触发器。

  示例代码:

 1 create trigger tri_NowOrderPrice4
 2 on dbo.Store after insert,update,delete
 3 as
 4 begin
 5     if exists(select *from inserted) and exists(select *from deleted)
 6         begin
 7             print('update');
 8             declare @price1 money;
 9             declare @price2 money;
10             declare @datetime datetime;
11             select @price1=ProductPrice from deleted;
12             select @price2=ProductPrice from inserted;
13             if @price1!=@price2
14                 begin
15                     declare @ProductID int;
16                     select @ProductID=ProductID from inserted
17                     insert into Logs(ID,operatedatetime,ProductID,oldprice,newprice)
18                     values(newid(),convert(datetime,getdate()),@ProductID,@price1,@price2)
19                     
20                     select *from dbo.Logs
21                 end
22         end
23     else if exists(select *from inserted)
24         begin
25             print('insert');
26         end
27     else if exists(select *from deleted)
28         begin
29             print('delete');
30         end
31     else
32         begin
33             print('others');
34         end
35 end

  触发器就是这个内容,有关触发器的一部分扑朔迷离操作希望大家有时间研商下,讲的不好请大家多多指正,希望我们学好t-sql语言。

  未来继续整治编程相关内容,希望大家多多关心。。。。

  

AS

INSERT weblog(activty) SELECT user_name FROM INSERTED

该触发器和眼前的触发器极度相像,除了以下两点以外:

该触发器在有记录插入表格webusers时接触;该触发器是FOR INSERT。

该触发器把记录从Inserted表拷贝到weblog表内。

Inserted表内包括了独具曾经插入到表内的新记录。如果一个新用户的全名插入到webusers表内时,触发器会活动地把新的用户姓名从webusers表拷贝到weblog表内。

当您想采用一个粗略的表来记录所有暴发在你数据库中一个要命首要的表的动作时,那种复制数据的法子非凡实惠。你可以选择该表来获得对您的数据库的移动的记录,并且可以用于记录和确诊一些或许暴发的标题。

您同一可以运用Inserted表和Deleted表来记录UPDATE对触发器所在的表所做的转移。当一个和触发器相关的表内的多寡被改动时,Deleted表包罗了具有列在改动此前的值,而Inserted表包涵了富有列在改动之后的值。参看上边的表12.2,以明确每一个动作是怎样影响Deleted和Inserted表的。

表12.2.Inserted和Deleted表的内容

INSERT

DELETE

UPDATE

Inserted

插入列

修改前的列

Deleted

删除列

修改后的列

 

 

 

 

 

 

 

 

 

 使用 inserted 和 deleted 表

 (2009-03-12 12:44:13)

转载

标签: 

杂谈

分类: 工作所用

使用 inserted 和 deleted 表 updated
触发器语句中利用了三种独特的表:deleted 表和 inserted 表。Microsoft® SQL
Server™ 2000
自动成立和保管那几个表。可以行使那八个临时的驻留内存的表测试某些数据修改的效用及安装触发器操作的尺码;然则,无法一直对表中的数码举办变更。

inserted 和 deleted 表主要用来触发器中:

扩张表间引用完整性。

在以视图为底蕴的基表中插入或更新数据。

自我批评错误并基于错误选取行动。

找到数据修改前后表状态的歧异,并基于此差别选择行动。
Deleted 表用于存储 DELETE 和 UPDATE 语句所影响的行的副本。在实施 DELETE
或 UPDATE 语句时,行从触发器表中删除,并传导到 deleted 表中。Deleted
表和触发器表平常没有一样的行。

Inserted 表用于存储 INSERT 和 UPDATE
语句所影响的行的副本。在一个插入或更新事务处理中,新招商银行被同时加上到
inserted 表和触发器表中。Inserted 表中的行是触发器表中新行的副本。

履新工作类似于在剔除之后执行插入;首先旧行被复制到 deleted
表中,然后新行被复制到触发器表和 inserted 表中。

在安装触发器条件时,应当为引发触发器的操作方便使用 inserted 和 deleted
表。就算在测试 INSERT 时引用 deleted 表或在测试 DELETE 时引用 inserted
表不会滋生其他不当,但是在那种情状下那个触发器测试表中不会含有其他行。

 

申明  倘诺触发器操作取决于一个多少修改所影响的行数,应该为多行数据修改(基于
SELECT 语句的 INSERT、DELETE 或 UPDATE)使用测试(如检查
@@ROWCOUNT),然后利用对应的预谋。

1.插入操作(Insert)

Inserted表有数量,Deleted表无多少

2.去除操作(Delete)

Inserted表无数据,Deleted表有多少

3.立异操作(Update)

Inserted表有数据(新数据),Deleted表有数量(旧数据)
SQL Server™ 2000 不允许 AFTER 触发器引用 inserted 和 deleted 表中的
text、ntext 或 image 列;但是,允许 INSTEAD OF
触发器引用这一个列。有关越多音信,请参见 CREATE TRIGGER。

 

Inserted为空,Deleted不为空   –Delete
Inserted不为空,Deleted为空   –Insert
Inserted不为空,Deleted不为空   –Update

 

alter TRIGGER update_oatable_state
ON oatable
FOR update
AS

declare @zid nvarchar(100)
declare @sub2 nvarchar(100)

select  @zid=zid, @sub2=sub2   from   updated
997755.com澳门葡京, update   T_P_OA_ZZWJGL   set   v5=@sub2 where zid = @zid

GO

假使您担保每一次只更新一条记下: 
  
  CREATE   TRIGGER   UpdateUser   ON   dbo.[user]   
  after   update 
  AS 
  update   users   set   userid=new.UserName,[password]=new.UserPassword   from   inserted   new  where   users.userid=(select   username   from   deleted) 
  go

 

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website