Correctly understand the DML triggers and the DDL triggers (and the structure of the EVENT_INSTANCE)

For some reason, I have some misconceptions about triggers. Here is the correct understanding:

·       DML Triggers (or triggers for DML Events) can be AFTER (or FOR) or INSTEAD OF triggers. It is also true for the Azure off-premise database. See the Syntax below:

Trigger on an INSERT, UPDATE, or DELETE statement to a table or view (DML Trigger)

CREATE TRIGGER [ schema_name . ]trigger_name
ON { table | view }
[ WITH <dml_trigger_option> [ ,...n ] ]
{ FOR | AFTER | INSTEAD OF }
{ [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] }
[ WITH APPEND ]
[ NOT FOR REPLICATION ]
AS { sql_statement  [ ; ] [ ,...n ] | EXTERNAL NAME <method specifier [ ; ] > }

<dml_trigger_option> ::=
    [ ENCRYPTION ]
    [ EXECUTE AS Clause ]

<method_specifier> ::= 
    assembly_name.class_name.method_name

·       DDL Triggers (or triggers for DDL Events) can only be AFTER (or FOR) triggers. No INSTEAD OF triggers for DDL events. See the Syntax below:

Trigger on a CREATE, ALTER, DROP, GRANT, DENY, REVOKE, or UPDATE STATISTICS statement (DDL Trigger)
CREATE TRIGGER trigger_name
ON { ALL SERVER | DATABASE }
[ WITH <ddl_trigger_option> [ ,...n ] ]
{ FOR | AFTER } { event_type | event_group } [ ,...n ]
AS { sql_statement  [ ; ] [ ,...n ] | EXTERNAL NAME < method specifier >  [ ; ] }

<ddl_trigger_option> ::=
    [ ENCRYPTION ]
    [ EXECUTE AS Clause ]

·       LOGON Triggers (or triggers for LogOn Events), the same as DDL Triggers, can only be AFTER trigger, no INSTEAD OF trigger. See the Syntax below:

Trigger on a LOGON event (Logon Trigger)

CREATE TRIGGER trigger_name
ON ALL SERVER
[ WITH <logon_trigger_option> [ ,...n ] ]
{ FOR| AFTER } LOGON 
AS { sql_statement  [ ; ] [ ,...n ] | EXTERNAL NAME < method specifier >  [ ; ] }

<logon_trigger_option> ::=
    [ ENCRYPTION ]
    [ EXECUTE AS Clause ]

DDL Triggers can be of two scopes.
·       Server Level Trigger – To capture events for all Databases on the Server,
·       Database Level Trigger – Limited to a single Database on which the Trigger is created.

DDL Trigger often captures the information about the EVENT that fired it by using EVENTDATA()function. EVENTDATA() returns an XML. The following example not only captures the DDL EVENT Type, but the entire structure of the Event Data as well:

--A trigger that works with DDL statements
CREATE TRIGGER Database_CreateTable_DropTable
ON DATABASE
AFTER CREATE_TABLE, DROP_TABLE
AS
    DECLARE @EventData XML;
    SELECT  @EventData = EVENTDATA();
    DECLARE @EventType VARCHAR(100);
    SET @EventType = @EventData.value('(/EVENT_INSTANCE/EventType)[1]',
                                      'varchar(100)');
    IF @EventType = 'CREATE_TABLE'
        PRINT 'A new table has been created.';
    ELSE
        PRINT 'A table has been dropped.';
    PRINT CONVERT(VARCHAR(MAX), @EventData);

--A CREATE TABLE statement that fires the trigger
CREATE TABLE VendorsTest
    (
        VendorID INT ,
        VendorName VARCHAR(50)
    );

/*
The response from the system:

A new table has been created.
*/

-- Below shows the structure of the Event Data or EVENT_INSTANCE:

<EVENT_INSTANCE>
    <EventType>CREATE_TABLE</EventType>
    <PostTime>2012-05-09T17:01:15.390</PostTime>
    <SPID>51</SPID>
    <ServerName>ANNE-PC\SQLEXPRESS</ServerName>
    <LoginName>murach\Anne</LoginName>
    <UserName>dbo</UserName>
    <DatabaseName>AP</DatabaseName>
    <SchemaName>dbo</SchemaName>
    <ObjectName>VendorsTest</ObjectName>
    <ObjectType>TABLE</ObjectType>
    <TSQLCommand>
        <SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON"
        ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON"
        ENCRYPTED="FALSE"/>
        <CommandText>
            CREATE TABLE VendorsTest (VendorID int,
            VendorName varchar(50));
        </CommandText>
    </TSQLCommand>

</EVENT_INSTANCE>