All Products
Search
Document Center

Use SSMS and BCP to migrate a SQL Server database

Last Updated: Oct 30, 2018

This article describes how to use SQL Server Management Studio (SSMS) and the Bulk Copy Program (BCP) to migrate the data of a SQL Server database, based on an example of full migration from a local SQL Server database to a SQL Server 2012 database of ApsaraDB for RDS.

Application scenarios

  • Schema migration from an SQL Server database.

  • Full migration (incremental migration not supported).

  • Full migration between local databases, from a local database to a SQL Server database of ApsaraDB for RDS, and between SQL Server databases of ApsaraDB for RDS.

Background information

SSMS provides an integrated environment for managing the basic architecture of SQL Server. You can use the tools of SSMS to configure, monitor, and manage your SQL Server instances. SSMS also provides the tools for deploying, monitoring, and upgrading data-layer components, such as the databases and data warehouses used by application programs. You can use the tools to generate queries and scripts.

BCP can be used to copy large volumes of data between SQL Server instances and between data files in specified formats. It can also be used to import many new rows to an SQL Server table and export table data to data files.

This article describes how to use SSMS to generate the script used to create the object structure of the source database and run the script in the target database for database schema migration, and how to use the BCP command line to export and import data from/to databases for full migration. The following describes how to migrate full data from the local SQL Server 2012 database AdventureWorks2012 to a SQL Server 2012 database of ApsaraDB for RDS.

Prerequisites

There must be enough storage space in the target database to import the data and log files. The total size of the two parts is about 2-3 times as that of the source database if the database is in Full mode. If the target database is in the local user-created environment, make sure that the host has enough storage space. If the database is on the SQL Server instance of ApsaraDB for RDS, make sure that you have purchased enough storage space.

Attentions

  • When creating the target database, make sure that the source and target database have the same sorting rules. Otherwise, full migration may fail.

  • To avoid errors and improve the data import efficiency during full migration, you must disable the foreign keys, indexes, and triggers of the target database, and re-enable them after migration.

  • When BCP imports the timestamp column or computed column, these column values are ignored. The SQL Server automatically assigns these values.

Procedure

  1. Start the SSMS client.

  2. Connect to the source database AdventureWorks2012 and the target SQL Server database of ApsaraDB for RDS.

  3. Run the following code to create a user with read and write permissions in the source database. In the code, testdbo is the username, and XXXXXXXX is the user’s logon password. Set the two parameters to the expected username and password before you run the code. Skip this step if your database has a user with read and write permissions.

    1. USE MASTER
    2. GO
    3. CREATE LOGIN testdbo
    4. WITH PASSWORD = N'XXXXXXXX',CHECK_POLICY = OFF
    5. GO
    6. USE AdventureWorks2012
    7. GO
    8. CREATE USER testdbo FOR LOGIN testdbo;
    9. EXEC sys.sp_addrolemember 'db_owner','testdbo'
    10. GO
  4. Disable the TCP/IP protocol to terminate all the client connections established to the source database. This guarantees data consistency for the source database before and after migration.

  5. Restart the SQL Server service.

    Note: After the TCP/IP protocol is disabled, remote application programs cannot access the local instance through the TCP/IP port. You must export data using BCP on the physical machine where the instance runs.

  6. Run the following command to create a database on the SQL Server 2012 instance of ApsaraDB for RDS.

    1. create database db01 DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;
  7. Run the following command to check the sorting rules of the source and target database.

    1. -- Check Collation name
    2. SELECT name,collation_name
    3. FROM sys.databases
    4. WHERE name = 'adventureworks2012'
  8. If the returned results show that the source and target database have different sorting rules, run the following code to replace SQL_Latin1_General_CP1_CI_AS with the same sorting rule as that of the source database. Skip this step if the source and target database have the same sorting rules.

    1. -- change the collate if need.
    2. USE master;
    3. GO
    4. ALTER DATABASE adventureworks2012
    5. COLLATE SQL_Latin1_General_CP1_CI_AS;
    6. GO
  9. Run the following command in the target database to create the same user as the source database user created in Step 3.

    1. USE MASTER
    2. GO
    3. CREATE LOGIN testdbo
    4. WITH PASSWORD = N'XXXXXXXX',CHECK_POLICY = OFF
    5. GO
    6. USE AdventureWorks2012
    7. GO
    8. CREATE USER testdbo FOR LOGIN testdbo;
    9. EXEC sys.sp_addrolemember 'db_owner','testdbo'
    10. GO
  10. In the source database, generate the script used to create object information. The procedure is as follows:

    1. In the source database, click Databases.

    2. Right-click AdventureWorks2012.

    3. Choose Tasks > Generate Scripts from the shortcut menu.

      Generate a script

    4. The script generation page appears. Click Next.

    5. Click Select specific database objects and select all migration objects except Users. Click Next.

      Select migration objects

    6. On the Set Scripting Options page, click Advanced and complete the following settings:

      • Click Script for Server Version and set the value to the target database version. This example uses SQL Server 2012.

      • Click Script for the database engine edition and set the value to Microsoft SQL Server Enterprise Edition.

      • Set Script Object-Level Permissions, Script Owner, and Script USE DATAABASE to True.

      • Click Types of data to script and set the value to Schema only.

        Note: Do not set “Types of data to script” to “Schema and data”. Otherwise, a schema file and an INSERT statement file are generated, reducing efficiency.

      • We recommend that you set all options in Table/View Options to True.

        Advanced script settings

    7. Click OK. The exported script file is displayed under File name on the page.

    8. Click Next, Next, and Finish in sequence to complete script generation.

  11. Run the generated script in the target database.

  12. After the script for creating object information is executed, run the following command and set “@is_disable BIT” to 1 to disable foreign key constraints, indexes, and triggers.

    Note: Foreign key constraints cause the data import to fail, while indexes and triggers reduce the efficiency of the data import. Therefore, they must be disabled.

    1. USE [adventureworks2012]
    2. GO
    3. --public variables: need init by users.
    4. DECLARE
    5. @is_disable BIT = 1 -- 1: disalbe indexes, foreign keys and triggers;
    6. -- 0: enable indexes, foreign keys and triggers;
    7. ;
    8. --================ Private variables
    9. DECLARE
    10. @sql NVARCHAR(MAX)
    11. , @sql_index NVARCHAR(MAX)
    12. , @tb_schema SYSNAME
    13. , @tb_object_name SYSNAME
    14. , @tr_schema SYSNAME
    15. , @tr_object_name SYSNAME
    16. , @ix_name SYSNAME
    17. ;
    18. --================= Disable/Enable indexes on all tables
    19. DECLARE
    20. cur_indexes CURSOR LOCAL STATIC FORWARD_ONLY READ_ONLY
    21. FOR
    22. SELECT
    23. ix_name = ix.name
    24. , tb_schema = SCHEMA_NAME(obj.schema_id)
    25. , tb_object_name = obj.name
    26. FROM sys.indexes as ix
    27. INNER JOIN sys.objects as obj
    28. ON ix.object_id = obj.object_id
    29. WHERE ix.type >= 2
    30. AND obj.is_ms_shipped = 0
    31. AND ix.is_disabled = (1 - @is_disable)
    32. OPEN cur_indexes;
    33. FETCH NEXT FROM cur_indexes INTO @ix_name, @tb_schema, @tb_object_name;
    34. WHILE @@FETCH_STATUS = 0
    35. BEGIN
    36. SET
    37. @sql_index = N'ALTER INDEX ' + QUOTENAME(@ix_name)
    38. + N' ON ' + QUOTENAME(@tb_schema) + N'.' + QUOTENAME(@tb_object_name)
    39. + CASE @is_disable
    40. WHEN 1 THEN N' DISABLE;'
    41. WHEN 0 THEN N' REBUILD; '
    42. ELSE N''
    43. END;
    44. RAISERROR(N'%s', 10, 1, @sql_index) WITH NOWAIT;
    45. EXEC sys.sp_executesql @sql_index
    46. FETCH NEXT FROM cur_indexes INTO @ix_name, @tb_schema, @tb_object_name;
    47. END
    48. CLOSE cur_indexes;
    49. DEALLOCATE cur_indexes;
    50. --================= Disable/Enable foreign keys on all tables
    51. --disable
    52. IF @is_disable = 1
    53. BEGIN
    54. SELECT
    55. @sql = N'
    56. RAISERROR(N''ALTER TABLE ? NOCHECK CONSTRAINT ALL;'', 10, 1) WITH NOWAIT
    57. ALTER TABLE ? NOCHECK CONSTRAINT ALL;'
    58. ;
    59. END
    60. ELSE --enable
    61. BEGIN
    62. SELECT
    63. @sql = N'
    64. RAISERROR(N''ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL;'', 10, 1) WITH NOWAIT
    65. ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL;'
    66. ;
    67. END
    68. EXEC sys.sp_MSforeachtable @sql
    69. --================= Disable/Enable triggers on all tables
    70. DECLARE
    71. cur_triggers CURSOR LOCAL STATIC FORWARD_ONLY READ_ONLY
    72. FOR
    73. SELECT
    74. tb_schema = SCHEMA_NAME(tb.schema_id)
    75. ,tb_object_name = tb.name
    76. ,tr_schema = SCHEMA_NAME(obj.schema_id)
    77. ,tr_object_name = obj.name
    78. FROM sys.objects as obj
    79. INNER JOIN sys.tables as tb
    80. ON obj.parent_object_id = tb.object_id
    81. INNER JOIN sys.triggers as tr
    82. ON obj.object_id = tr.object_id
    83. WHERE obj.type = 'TR'
    84. AND obj.is_ms_shipped = 0
    85. AND tr.is_disabled = (1 - @is_disable)
    86. ORDER BY tb_schema, tb_object_name
    87. OPEN cur_triggers;
    88. FETCH NEXT FROM cur_triggers INTO @tb_schema, @tb_object_name, @tr_schema, @tr_object_name;
    89. WHILE @@FETCH_STATUS = 0
    90. BEGIN
    91. SET @sql = CASE @is_disable
    92. WHEN 1 THEN N'DISABLE TRIGGER '
    93. WHEN 0 THEN N'ENABLE TRIGGER '
    94. ELSE N''
    95. END
    96. + QUOTENAME(@tr_schema) + N'.' + QUOTENAME(@tr_object_name)
    97. + N' ON '
    98. + QUOTENAME(@tb_schema) + N'.' + QUOTENAME(@tb_object_name)
    99. ;
    100. RAISERROR(N'%s', 10, 1, @sql) WITH NOWAIT;
    101. EXEC sys.sp_executesql @sql;
    102. FETCH NEXT FROM cur_triggers INTO @tb_schema, @tb_object_name, @tr_schema, @tr_object_name;
    103. END
    104. CLOSE cur_triggers;
    105. DEALLOCATE cur_triggers;
    106. GO
  13. Run the following command in the source and target databases to obtain their object information.

    1. USE AdventureWorks2012
    2. GO
    3. ;WITH objs
    4. AS(
    5. -- check objects
    6. SELECT
    7. database_name = LOWER(DB_NAME())
    8. , object_type = type
    9. , objet_desc = type_desc
    10. , object_count = COUNT(1)
    11. FROM sys.all_objects WITH(NOLOCK)
    12. WHERE is_ms_shipped = 0
    13. GROUP BY type,type_desc
    14. UNION ALL
    15. --check indexes
    16. SELECT
    17. database_name = LOWER(DB_NAME())
    18. , object_type = CAST(ix.type AS VARCHAR)
    19. , objet_desc = ix.type_desc
    20. , object_count = COUNT(1)
    21. FROM sys.indexes as ix
    22. INNER JOIN sys.objects as obj
    23. ON ix.object_id = obj.object_id
    24. WHERE obj.is_ms_shipped = 0
    25. GROUP BY ix.type,ix.type_desc
    26. )
    27. SELECT * FROM objs
    28. ORDER BY object_type
  14. Compare the object information of the source and target databases in the returned results. If the source and target database have the same object information, it indicates that the object information has been migrated from the source to the target database.

    Note:

    • We recommend that you use a comparison tool to compare the object information of the source and target databases and to avoid human errors. We recommend that you use Araxis Merge 2001 v6.0 Professional for the comparison.

    • The name of the target SQL Server database of ApsaraDB for RDS only supports lowercase letters, while the name of the source database may contain uppercase letters. When using a comparison tool, set the tool to skip uppercase/lowercase letter check. If you use Araxis Merge 2001 v6.0 Professional, choose View > Options and select Ignore differences in character case.

  15. Set the following parameters according to the actual condition and run the following script in the source database.

    • source_User: Username for logging on to the source database.

    • source_Password: Password for the username for logging on to the source database.

    • destination_Instance: Replace XXXX with the instance name for the target database.

    • destination_Database: Name of the target database. If this parameter is empty, the target database name is the same as the source database name.

    • destination_User: Username for logging on to the target database, which must be the same as the source database username.

    • destination_Password: Password for the username for logging on to the target database.

      1. USE AdventureWorks2012
      2. GO
      3. -- declare public variables, need to init by user
      4. DECLARE
      5. @source_Instance sysname
      6. , @source_Database sysname
      7. , @source_User sysname
      8. , @source_Passwd sysname
      9. , @destination_Instance sysname
      10. , @destination_Database sysname
      11. , @destination_User sysname
      12. , @destination_Passwd sysname
      13. , @batch_Size int
      14. , @transfer_table_list nvarchar(max)
      15. ;
      16. -- Public variables init.
      17. SELECT
      18. @source_Instance = @@SERVERNAME -- Source Instance Name
      19. , @source_Database = DB_NAME() -- Source Database is current database.
      20. , @source_User = 'XXX' -- Source Instance Connect User Name
      21. , @source_Passwd = N'XXX' -- Source Instance User Password
      22. , @destination_Instance = N'XXXX.sqlserver.rds.aliyuncs.com,3433' -- Destination Instance Name
      23. , @destination_Database = N'' -- Destination Database name: NULL/empty: Keep the same as source db
      24. , @destination_User = 'XXX' -- Destination Instance User Name
      25. , @destination_Passwd = N'XXX' -- Destination Instance User Password
      26. , @transfer_table_list = N'' --NULL/empty: ALL Tables are needed to be transfered.
      27. , @batch_Size = 50000 -- BCP IN Batch Size, by default, it is 50000. Must between 1 and 50000.
      28. ;
      29. -- Private variables, there is no need to init.
      30. DECLARE
      31. @transfer_table_list_xml xml
      32. , @timestamp char(14)
      33. ;
      34. -- correct the variables init by user.
      35. SELECT
      36. @source_Instance = RTRIM( LTRIM(@source_Instance) )
      37. , @source_User = RTRIM( LTRIM( @source_User ) )
      38. , @source_Passwd = RTRIM( LTRIM( @source_Passwd ) )
      39. , @destination_Instance = RTRIM( LTRIM( @destination_Instance ) )
      40. , @destination_Database = CASE
      41. WHEN ISNULL(@destination_Database, N'') = N'' THEN @source_Database
      42. ELSE @destination_Database
      43. END
      44. , @destination_User = RTRIM( LTRIM( @destination_User ) )
      45. , @destination_Passwd = RTRIM( LTRIM( @destination_Passwd ) )
      46. , @batch_Size = CASE
      47. WHEN (@batch_Size>0 AND @batch_Size<=50000) THEN @batch_Size
      48. ELSE 50000
      49. END
      50. , @transfer_table_list_xml = '<V><![CDATA[' + REPLACE(
      51. REPLACE(
      52. REPLACE(
      53. @transfer_table_list,CHAR(10),']]></V><V><![CDATA['
      54. ),',',']]></V><V><![CDATA['
      55. ),CHAR(13),']]></V><V><![CDATA['
      56. ) + ']]></V>'
      57. , @timestamp =
      58. REPLACE(
      59. REPLACE(
      60. REPLACE(
      61. CONVERT(CHAR(19), GETDATE(), 120), N'-', '')
      62. , N':', N'')
      63. , CHAR(32), N'')
      64. ;
      65. IF OBJECT_ID('tempdb..#tb_list', 'U') IS NOT NULL
      66. DROP TABLE #tb_list
      67. CREATE TABLE #tb_list(
      68. RowID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY
      69. ,Table_name SYSNAME NOT NULL
      70. )
      71. IF ISNULL(@transfer_table_list, '') = ''
      72. BEGIN
      73. INSERT INTO #tb_list
      74. SELECT name
      75. FROM sys.tables AS tb
      76. WHERE tb.is_ms_shipped = 0
      77. END
      78. ELSE
      79. BEGIN
      80. INSERT INTO #tb_list
      81. SELECT table_name = T.C.value('(./text())[1]','sysname')
      82. FROM @transfer_table_list_xml.nodes('./V') AS T(C)
      83. WHERE T.C.value('(./text())[1]','sysname') IS NOT NULL
      84. END
      85. ;
      86. SELECT
      87. BCP_OUT = N'BCP ' + @source_Database + '.' + sch.name + '.' + tb.name
      88. + N' Out '
      89. + QUOTENAME( REPLACE(@source_Instance, N'\', N'_')+ '.' + @source_Database + '.' + sch.name + '.' + tb.name, '"')
      90. + N' /N /U ' + @source_User +N' /P ' + @source_Passwd +N' /S ' + @source_Instance
      91. + N' >> BCPOUT_' + @timestamp +N'.txt'
      92. ,BCP_IN = N'BCP ' + @destination_Database + '.' + sch.name + '.' + tb.name
      93. + N' In '
      94. + QUOTENAME( REPLACE(@source_Instance, N'\', N'_')+ '.' + @source_Database + '.' + sch.name + '.' + tb.name, '"')
      95. + N' /N /E /q /k /U ' + @destination_User + N' /P ' + @destination_Passwd + N' /b '
      96. + CAST(@batch_Size as varchar) + N' /S ' + @destination_Instance
      97. + N' >> BCPIN_' + @timestamp + N'.txt'
      98. --,*
      99. FROM sys.tables as tb
      100. LEFT JOIN sys.schemas as sch
      101. ON tb.schema_id = sch.schema_id
      102. WHERE tb.is_ms_shipped = 0
      103. AND tb.name IN (SELECT Table_name FROM #tb_list)
  16. Save the generated BCP_OUT and BCP_IN files to the local computer.

  17. Run the local BCP_OUT.bat file to generate data export files for the source database.

  18. After the BCP_OUT.bat file is executed, double-click its log file BCPOUT_YYYYMMDDHHMMSS.txt (YYYYMMDDHHMMSS is the file generation time) to check whether all data is successfully exported.

  19. Run the local BCP_IN.bat file to import the files that have been exported from the source database to the remote target database.

    NOTE: The target database is in Alibaba Cloud. Due to network conditions, it takes a longer time to run the BCP_IN.bat file than the BCP_OUT.bat file.

  20. After the BCP_IN.bat file is executed, double-click its log file BCPOUT_YYYYMMDDHHMMSS.txt to check whether all data is successfully imported.

  21. After you verify that all the data has been imported from the source to the target database, delete the intermediate temporary files that BCP exports in Step 17 from the disk. See the following figure.

    Files exported by BCP

  22. Run the following code in the source and target databases to check the total number of table records in the two databases.

    1. USE AdventureWorks2012
    2. GO
    3. SELECT
    4. schema_name = SCHEMA_NAME(tb.schema_id)
    5. ,table_name = OBJECT_NAME(tb.object_id)
    6. ,row_count = SUM(CASE WHEN ps.index_id < 2 THEN ps.row_count ELSE 0 END)
    7. FROM sys.dm_db_partition_stats as ps WITH(NOLOCK)
    8. INNER JOIN sys.tables as tb WITH(NOLOCK)
    9. ON ps.object_id = tb.object_id
    10. WHERE tb.is_ms_shipped = 0
    11. GROUP BY tb.object_id,tb.schema_id
    12. ORDER BY schema_name,table_name
  23. Use a comparison tool to compare the total number of table records in the source and target databases. If the source and target database have the same number of table records, all the data has been imported from the source to the target database.

  24. Run the following code and set “@is_disable BIT” to 0 to enable foreign key constraints, indexes, and triggers. This completes database migration.

    1. USE [adventureworks2012]
    2. GO
    3. --public variables: need init by users.
    4. DECLARE
    5. @is_disable BIT = 1 -- 1: disalbe indexes, foreign keys and triggers;
    6. -- 0: enable indexes, foreign keys and triggers;
    7. ;
    8. --================ Private variables
    9. DECLARE
    10. @sql NVARCHAR(MAX)
    11. , @sql_index NVARCHAR(MAX)
    12. , @tb_schema SYSNAME
    13. , @tb_object_name SYSNAME
    14. , @tr_schema SYSNAME
    15. , @tr_object_name SYSNAME
    16. , @ix_name SYSNAME
    17. ;
    18. --================= Disable/Enable indexes on all tables
    19. DECLARE
    20. cur_indexes CURSOR LOCAL STATIC FORWARD_ONLY READ_ONLY
    21. FOR
    22. SELECT
    23. ix_name = ix.name
    24. , tb_schema = SCHEMA_NAME(obj.schema_id)
    25. , tb_object_name = obj.name
    26. FROM sys.indexes as ix
    27. INNER JOIN sys.objects as obj
    28. ON ix.object_id = obj.object_id
    29. WHERE ix.type >= 2
    30. AND obj.is_ms_shipped = 0
    31. AND ix.is_disabled = (1 - @is_disable)
    32. OPEN cur_indexes;
    33. FETCH NEXT FROM cur_indexes INTO @ix_name, @tb_schema, @tb_object_name;
    34. WHILE @@FETCH_STATUS = 0
    35. BEGIN
    36. SET
    37. @sql_index = N'ALTER INDEX ' + QUOTENAME(@ix_name)
    38. + N' ON ' + QUOTENAME(@tb_schema) + N'.' + QUOTENAME(@tb_object_name)
    39. + CASE @is_disable
    40. WHEN 1 THEN N' DISABLE;'
    41. WHEN 0 THEN N' REBUILD; '
    42. ELSE N''
    43. END;
    44. RAISERROR(N'%s', 10, 1, @sql_index) WITH NOWAIT;
    45. EXEC sys.sp_executesql @sql_index
    46. FETCH NEXT FROM cur_indexes INTO @ix_name, @tb_schema, @tb_object_name;
    47. END
    48. CLOSE cur_indexes;
    49. DEALLOCATE cur_indexes;
    50. --================= Disable/Enable foreign keys on all tables
    51. --disable
    52. IF @is_disable = 1
    53. BEGIN
    54. SELECT
    55. @sql = N'
    56. RAISERROR(N''ALTER TABLE ? NOCHECK CONSTRAINT ALL;'', 10, 1) WITH NOWAIT
    57. ALTER TABLE ? NOCHECK CONSTRAINT ALL;'
    58. ;
    59. END
    60. ELSE --enable
    61. BEGIN
    62. SELECT
    63. @sql = N'
    64. RAISERROR(N''ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL;'', 10, 1) WITH NOWAIT
    65. ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL;'
    66. ;
    67. END
    68. EXEC sys.sp_MSforeachtable @sql
    69. --================= Disable/Enable triggers on all tables
    70. DECLARE
    71. cur_triggers CURSOR LOCAL STATIC FORWARD_ONLY READ_ONLY
    72. FOR
    73. SELECT
    74. tb_schema = SCHEMA_NAME(tb.schema_id)
    75. ,tb_object_name = tb.name
    76. ,tr_schema = SCHEMA_NAME(obj.schema_id)
    77. ,tr_object_name = obj.name
    78. FROM sys.objects as obj
    79. INNER JOIN sys.tables as tb
    80. ON obj.parent_object_id = tb.object_id
    81. INNER JOIN sys.triggers as tr
    82. ON obj.object_id = tr.object_id
    83. WHERE obj.type = 'TR'
    84. AND obj.is_ms_shipped = 0
    85. AND tr.is_disabled = (1 - @is_disable)
    86. ORDER BY tb_schema, tb_object_name
    87. OPEN cur_triggers;
    88. FETCH NEXT FROM cur_triggers INTO @tb_schema, @tb_object_name, @tr_schema, @tr_object_name;
    89. WHILE @@FETCH_STATUS = 0
    90. BEGIN
    91. SET @sql = CASE @is_disable
    92. WHEN 1 THEN N'DISABLE TRIGGER '
    93. WHEN 0 THEN N'ENABLE TRIGGER '
    94. ELSE N''
    95. END
    96. + QUOTENAME(@tr_schema) + N'.' + QUOTENAME(@tr_object_name)
    97. + N' ON '
    98. + QUOTENAME(@tb_schema) + N'.' + QUOTENAME(@tb_object_name)
    99. ;
    100. RAISERROR(N'%s', 10, 1, @sql) WITH NOWAIT;
    101. EXEC sys.sp_executesql @sql;
    102. FETCH NEXT FROM cur_triggers INTO @tb_schema, @tb_object_name, @tr_schema, @tr_object_name;
    103. END
    104. CLOSE cur_triggers;
    105. DEALLOCATE cur_triggers;
    106. GO