Lorenzo Alberton
« Articles
Extracting META information from SQL Server (INFORMATION_SCHEMA)
Abstract: How to retrieve META information from Microsoft SQL Server, using the INFORMATION_SCHEMA, with system tables (sysobjects, sysindexkeys, sysindexes, syscolumns, systypes, etc) and/or with system stored procedures (T-SQL).
Following my tutorials on how to extract meta informations from Firebird SQL and from PostgreSQL, I'm now going to show how to retrieve the same informations from Microsoft SQL Server, using the INFORMATION_SCHEMA
, with system tables (sysobjects, sysindexkeys, sysindexes, syscolumns, systypes
, etc) and/or with system stored procedures (T-SQL).
SQL Server 2005 introduced some catalog views called "sys.*": for completeness, I may use them too in the queries. To list all the views available in the INFORMATION_SCHEMA, you can run the following query from the 'master' database:
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.Views WHERE TABLE_SCHEMA = 'INFORMATION_SCHEMA' ORDER BY TABLE_NAME;
Test data
We need a few sample tables, indices and views to test the following queries, so let's create them. We also create a sample TRIGGER and a function.
-- sample data to test SQL Server INFORMATION_SCHEMA -- TABLE TEST CREATE TABLE TEST ( TEST_NAME CHAR(30) NOT NULL, TEST_ID INTEGER DEFAULT '0' NOT NULL, TEST_DATE TIMESTAMP NOT NULL ); ALTER TABLE TEST ADD CONSTRAINT PK_TEST PRIMARY KEY (TEST_ID); -- TABLE TEST2 with some CONSTRAINTs and an INDEX CREATE TABLE TEST2 ( ID INTEGER NOT NULL, FIELD1 INTEGER, FIELD2 CHAR(15), FIELD3 VARCHAR(50), FIELD4 INTEGER, FIELD5 INTEGER, ID2 INTEGER NOT NULL ); ALTER TABLE TEST2 ADD CONSTRAINT PK_TEST2 PRIMARY KEY (ID2); ALTER TABLE TEST2 ADD CONSTRAINT TEST2_FIELD1ID_IDX UNIQUE (ID, FIELD1); ALTER TABLE TEST2 ADD CONSTRAINT TEST2_FIELD4_IDX UNIQUE (FIELD4); CREATE INDEX TEST2_FIELD5_IDX ON TEST2(FIELD5); -- TABLE NUMBERS CREATE TABLE NUMBERS ( NUMBER INTEGER DEFAULT '0' NOT NULL, EN CHAR(100) NOT NULL, FR CHAR(100) NOT NULL ); -- TABLE NEWTABLE CREATE TABLE NEWTABLE ( ID INT DEFAULT 0 NOT NULL, SOMENAME VARCHAR (12), SOMEDATE TIMESTAMP NOT NULL, SOMEDESCRIPTION VARCHAR(12) NULL ); ALTER TABLE NEWTABLE ADD CONSTRAINT PKINDEX_IDX PRIMARY KEY (ID); -- VIEW on TEST CREATE VIEW "testview"( TEST_NAME, TEST_ID, TEST_DATE ) AS SELECT * FROM TEST WHERE TEST_NAME LIKE 't%'; -- VIEW on NUMBERS CREATE VIEW "numbersview"( NUMBER, TRANS_EN, TRANS_FR ) AS SELECT * FROM NUMBERS WHERE NUMBER > 100; -- TRIGGER on NEWTABLE CREATE TRIGGER TEST_TRIGGER ON NEWTABLE FOR UPDATE AS DECLARE @oldName VARCHAR(100) DECLARE @newId INTEGER SELECT @oldName = (SELECT somename FROM Deleted) SELECT @newId = (SELECT id FROM Inserted) BEGIN UPDATE NEWTABLE SET somedescription = @oldName WHERE id = @newId; END; -- FUNCTION CREATE FUNCTION sum_decimal(@Number1 Decimal(6,2), @Number2 Decimal(6,2)) RETURNS Decimal(6,2) BEGIN DECLARE @Result Decimal(6,2) SET @Result = @Number1 + @Number2 RETURN @Result END; -- STORED PROCEDURE CREATE PROC getname AS SELECT SOMENAME FROM newtable; -- TABLEs for testing CONSTRAINTs CREATE TABLE testconstraints ( someid integer NOT NULL, somename character varying(10) NOT NULL, CONSTRAINT testconstraints_id_pk PRIMARY KEY (someid) ); CREATE TABLE testconstraints2 ( ext_id INT NOT NULL, modified DATETIME, uniquefield VARCHAR(10) NOT NULL, usraction INT NOT NULL, CONSTRAINT testconstraints_id_fk FOREIGN KEY (ext_id) REFERENCES testconstraints (someid) ON UPDATE CASCADE ON DELETE CASCADE, CONSTRAINT unique_2_fields_idx UNIQUE (modified, usraction), CONSTRAINT uniquefld_idx UNIQUE (uniquefield) )
List TABLEs
Here's the query that will return the names of the tables defined in the current database:
-- using the sp_tables system stored procedure: EXEC sp_tables @table_type = "'TABLE'"; -- using INFORMATION_SCHEMA: SELECT Owner = TABLE_SCHEMA, TableName = TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'IsMsShipped') = 0 ORDER BY TABLE_SCHEMA, TABLE_NAME; -- using the system tables: SELECT name FROM sysobjects WHERE xtype = 'U'; -- using the catalog views: SELECT name FROM sys.tables;
List VIEWs
Here's the query that will return the names of the VIEWs defined in the current database:
-- using the sp_tables system stored procedure: EXEC sp_tables @table_type = "'VIEW'", @table_owner = "dbo"; -- using INFORMATION_SCHEMA: SELECT Owner = TABLE_SCHEMA, TableName = TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'VIEW' AND OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'IsMsShipped') = 0 ORDER BY TABLE_SCHEMA, TABLE_NAME; -- using the system tables: SELECT name FROM sysobjects WHERE xtype = 'V'; -- using the catalog views: SELECT name FROM sys.views;
List users
SELECT DISTINCT loginame FROM master..sysprocesses; -- or EXEC sp_who 'active'; -- or SELECT name FROM sysusers;
List INDICES
Here's the query that will return the names of the INDICES defined in the TEST2 table (AFAIK, indices are not covered in the INFORMATION_SCHEMA):\
-- using the sysindexes system view: SELECT name FROM sysindexes WHERE OBJECT_NAME(id) = 'TEST2'; -- using the system stored procedures: EXEC sp_statistics @table_name="TEST2", @is_unique=N; -- or EXEC sp_helpindex "TEST2";
List CONSTRAINTs
Here's the query that will return the names of the CONSTRAINTs defined in the TEST2 table:
-- with INFORMATION_SCHEMA: SELECT constraint_name, constraint_type FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog = DB_NAME() AND table_name = 'TEST2'; -- using the system stored procedures: EXEC sp_pkeys @table_name="TEST2"; -- PKs EXEC sp_fkeys @pktable_name="TEST2"; -- FKs EXEC sp_statistics @table_name='TEST2', @is_unique=Y; -- Unique constraints -- or EXEC sp_helpconstraint "TEST2";
Detailed CONSTRAINT info
If you want to retrieve detailed info from any constraint (fields, type, rules, referenced table and fields for FOREIGN KEYs, etc.) given its name and table, here's the query to do so:
SELECT k.table_name, k.column_name field_name, c.constraint_type, CASE c.is_deferrable WHEN 'NO' THEN 0 ELSE 1 END 'is_deferrable', CASE c.initially_deferred WHEN 'NO' THEN 0 ELSE 1 END 'is_deferred', rc.match_option 'match_type', rc.update_rule 'on_update', rc.delete_rule 'on_delete', ccu.table_name 'references_table', ccu.column_name 'references_field', k.ordinal_position 'field_position' FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS c ON k.table_name = c.table_name AND k.table_schema = c.table_schema AND k.table_catalog = c.table_catalog AND k.constraint_catalog = c.constraint_catalog AND k.constraint_name = c.constraint_name LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc ON rc.constraint_schema = c.constraint_schema AND rc.constraint_catalog = c.constraint_catalog AND rc.constraint_name = c.constraint_name LEFT JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu ON rc.unique_constraint_schema = ccu.constraint_schema AND rc.unique_constraint_catalog = ccu.constraint_catalog AND rc.unique_constraint_name = ccu.constraint_name WHERE k.constraint_catalog = DB_NAME() AND k.table_name = 'testconstraints2' AND k.constraint_name = 'testconstraints_id_fk' ORDER BY k.constraint_name, k.ordinal_position;
List table fields
Here's the query that will return the names of the fields of the TEST2 table:
SELECT c.name FROM syscolumns c LEFT JOIN sysobjects o ON c.id = o.id WHERE o.name = 'test2' -- or SELECT c.name FROM sys.columns c JOIN sys.objects o ON c.object_id = o.object_id WHERE o.name = 'test2' -- with INFORMATION_SCHEMA: SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'test2';
Detailed table field info
If you want some more info about the field definitions, you can retrieve a larger subset of the fields available in the schema:
SELECT OBJECT_NAME(c.id) as table_name, c.name, t.name AS data_type, c.isnullable, com.text AS default_text, c.length, c.prec AS numeric_precision, c.scale AS numeric_scale, c.colorder FROM syscolumns c LEFT JOIN systypes t ON c.type = t.type AND c.xtype = t.xtype LEFT JOIN syscomments com ON com.id = c.cdefault WHERE OBJECT_NAME(c.id) = 'newtable' ORDER BY c.colorder; -- or SELECT o.name AS table_name, c.name, type_name(c.system_type_id) AS DATA_TYPE, c.is_nullable, object_definition(c.default_object_id) AS column_default, ColumnProperty(c.object_id, c.name, 'charmaxlen') AS length, c.precision AS numeric_precision, odbcscale(c.system_type_id, c.scale) AS numeric_scale, CollationProperty(c.collation_name, 'sqlcharsetname') AS character_set_name, c.collation_name, ColumnProperty(c.object_id, c.name, 'ordinal') AS ordinal_position FROM sys.objects o JOIN sys.columns c ON c.object_id = o.object_id WHERE o.name = 'newtable' -- with INFORMATION_SCHEMA: SELECT t.table_name, c.column_name 'name', c.data_type 'type', c.is_nullable, c.column_default, c.character_maximum_length 'length', c.numeric_precision, c.numeric_scale, c.character_set_name, c.collation_name, c.ordinal_position FROM INFORMATION_SCHEMA.TABLES t, INFORMATION_SCHEMA.COLUMNS c WHERE t.table_name = c.table_name AND t.table_name = 'newtable' ORDER BY c.ordinal_position;
List TRIGGERs
SELECT o.name FROM sysobjects o WHERE xtype = 'TR' AND OBJECTPROPERTY(o.id, 'IsMSShipped') = 0; -- or SELECT name FROM sys.triggers WHERE is_ms_shipped = 0;
List only the triggers for a given table:
SELECT o.name FROM sysobjects o WHERE xtype = 'TR' AND OBJECTPROPERTY(o.id, 'IsMSShipped') = 0 AND object_name(parent_obj) = 'newtable'; -- or SELECT name FROM sys.triggers WHERE is_ms_shipped = 0 AND object_name(parent_id) = 'newtable';
Detailed TRIGGER info
Show more informations about the trigger definitions:
SELECT sys1.name trigger_name, sys2.name table_name, c.text trigger_body, c.encrypted is_encripted, CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsTriggerDisabled') = 1 THEN 0 ELSE 1 END trigger_enabled, CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsertTrigger') = 1 THEN 'INSERT' WHEN OBJECTPROPERTY(sys1.id, 'ExecIsUpdateTrigger') = 1 THEN 'UPDATE' WHEN OBJECTPROPERTY(sys1.id, 'ExecIsDeleteTrigger') = 1 THEN 'DELETE' END trigger_event, CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsteadOfTrigger') = 1 THEN 'INSTEAD OF' ELSE 'AFTER' END trigger_type FROM sysobjects sys1 JOIN sysobjects sys2 ON sys1.parent_obj = sys2.id JOIN syscomments c ON sys1.id = c.id WHERE sys1.xtype = 'TR';
List FUNCTIONs
SELECT name FROM sysobjects WHERE xtype IN ('TF', 'FN', 'IF'); -- with INFORMATION_SCHEMA: SELECT routine_name FROM INFORMATION_SCHEMA.ROUTINES WHERE routine_type = N'FUNCTION';
List STORED PROCEDUREs
SELECT name FROM sysobjects WHERE xtype IN ('P', 'RF', 'X', 'PC'); -- or SELECT name FROM sys.procedures; -- with INFORMATION_SCHEMA: SELECT routine_name FROM INFORMATION_SCHEMA.ROUTINES WHERE routine_type = N'PROCEDURE';
What else?
If you'd like to see some other example queries, or have some comments and/or suggestions, just drop me a mail (you can find my address in the footer of this page) and I'll add them to this list.
HTH.
Related articles
- Extracting META information from Interbase/Firebird SQL (INFORMATION_SCHEMA)
- Extracting META information from Oracle (INFORMATION_SCHEMA)
- Extracting META information from PostgreSQL (INFORMATION_SCHEMA)
- Updated articles to extract META informations from databases
Latest articles
- On batching vs. latency, and jobqueue models
- Updated Kafka PHP client library
- Musings on some technical papers I read this weekend: Google Dremel, NoSQL comparison, Gossip Protocols
- Historical Twitter access - A journey into optimising Hadoop jobs
- Kafka proposed as Apache incubator project
- NoSQL Databases: What, When and Why (PHPUK2011)
- PHPNW10 slides and new job!
Filter articles by topic
AJAX, Apache, Book Review, Charset, Cheat Sheet, Data structures, Database, Firebird SQL, Hadoop, Imagick, INFORMATION_SCHEMA, JavaScript, Kafka, Linux, Message Queues, mod_rewrite, Monitoring, MySQL, NoSQL, Oracle, PDO, PEAR, Performance, PHP, PostgreSQL, Profiling, Scalability, Security, SPL, SQL Server, SQLite, Testing, Tutorial, TYPO3, Windows, Zend FrameworkFollow @lorenzoalberton
12 responses to "Extracting META information from SQL Server (INFORMATION_SCHEMA)"
AUSTIN HIGGS, 12 October 2009 13:42
Thank you for the trigger view with definition. It really helped me !!!!
Raj, 30 March 2010 00:33
Hi Alberton Is there any way to list all the "System Funtions" from DB. like min,max,round,Floor.... etc. possible please send me the queries and syntax Thanks a lot Raj
Kalyson, 13 September 2010 19:46
Hi, Alberton,
Great page! Just wondering if you knew a way to list indexes, too, especially if they are unique indexes...
Thanks! kalyson
Kalyson, 13 September 2010 19:48
Hi, Alberton,
Oh, I see indexes above... sorry!
--k
Larry Mehl, 08 October 2010 16:52
Lorenzo --
Thanks for these valuable utilities.
I need to find views containing a specific table (or, family of tables ... LIKE \\\'bv_%\\\').
Can you give me some direction on how to do that from the system tables?
Thanks in advance,
Larry Mehl
Raja, 15 March 2011 03:03
Hi, Alberton, It is very Help full.. thank u,
Helen Kresl, 26 May 2011 13:41
Lorenzo, I appreciate your post very much. I am wondering if you could show me how to retrieve a list of views containing references to specific column. My task is to find all views that contain a conditional reference to a column called "XYZ" (eg. Where clause comparing XYZ to bit value). This will enable me to give our developers a list of views that will be affected by a change to the "XYZ" column in the source table. Then I have to do that for all stored procedures....but could you assist me, or point me in the right direction, with how to do this with views?
Lorenzo Alberton, 29 May 2011 17:46
@Larry: With this query you can find the table(s) referenced by a view:
By reverting the query, you can select the views containing a table:
Lorenzo Alberton, 29 May 2011 17:53
@Helen: With this query you can list all the Views containing references to specific db/table/column:
dalex1973, 08 December 2011 08:56
There are some limitations for triggers extraction script: 1. Every Syscomments table row contains only 4000 characters of text, so if your trigger`s body length is larger than 4000, you will get several rows in syscomments - and script will return several rows. 2. Script returns only first type of action for trigger. (i.e FOR INSERT, UPDATE you will see INSERT only.)
My version of script:
SELECT sys1.NAME trigger_name, sys2.NAME table_name, (SELECT SS.[text] FROM sys.syscomments SS WHERE ss.id=sys1.id FOR XML PATH(\'\'),TYPE).query(\'text\').value(\'.\',\'nvarchar(max)\') trigger_body, (SELECT TOP 1 ss.encrypted FROM sys.syscomments ss WHERE ss.id=sys1.id) is_encrypted, CASE WHEN OBJECTPROPERTY(sys1.id, \'ExecIsTriggerDisabled\') = 1 THEN 0 ELSE 1 END trigger_enabled, STUFF(CASE WHEN OBJECTPROPERTY(sys1.id, \'ExecIsInsertTrigger\') = 1 THEN \',INSERT\' ELSE \'\' END + CASE WHEN OBJECTPROPERTY(sys1.id, \'ExecIsUpdateTrigger\') = 1 THEN \',UPDATE\' ELSE \'\' END + CASE WHEN OBJECTPROPERTY(sys1.id, \'ExecIsDeleteTrigger\') = 1 THEN \',DELETE\' ELSE \'\' END, 1, 1, \'\') trigger_event, CASE WHEN OBJECTPROPERTY(sys1.id, \'ExecIsInsteadOfTrigger\') = 1 THEN \'INSTEAD OF\' ELSE \'AFTER\' END trigger_type FROM sysobjects sys1 JOIN sysobjects sys2 ON sys1.parent_obj = sys2.id WHERE sys1.xtype = \'TR\';
Amir Hussein Samiani, 26 February 2012 10:11
SET NOCOUNT ON
DECLARE @table TABLE( RowId INT PRIMARY KEY IDENTITY(1, 1), ForeignKeyConstraintName NVARCHAR(200), ForeignKeyConstraintTableSchema NVARCHAR(200), ForeignKeyConstraintTableName NVARCHAR(200), ForeignKeyConstraintColumnName NVARCHAR(200), PrimaryKeyConstraintName NVARCHAR(200), PrimaryKeyConstraintTableSchema NVARCHAR(200), PrimaryKeyConstraintTableName NVARCHAR(200), PrimaryKeyConstraintColumnName NVARCHAR(200) )
INSERT INTO @table(ForeignKeyConstraintName, ForeignKeyConstraintTableSchema, ForeignKeyConstraintTableName, ForeignKeyConstraintColumnName) SELECT U.CONSTRAINT_NAME, U.TABLE_SCHEMA, U.TABLE_NAME, U.COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE U INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C ON U.CONSTRAINT_NAME = C.CONSTRAINT_NAME WHERE C.CONSTRAINT_TYPE = \'FOREIGN KEY\'
UPDATE @table SET PrimaryKeyConstraintName = UNIQUE_CONSTRAINT_NAME FROM @table T INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R ON T.ForeignKeyConstraintName = R.CONSTRAINT_NAME
UPDATE @table SET PrimaryKeyConstraintTableSchema = TABLE_SCHEMA, PrimaryKeyConstraintTableName = TABLE_NAME FROM @table T INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C ON T.PrimaryKeyConstraintName = C.CONSTRAINT_NAME
UPDATE @table SET PrimaryKeyConstraintColumnName = COLUMN_NAME FROM @table T INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE U ON T.PrimaryKeyConstraintName = U.CONSTRAINT_NAME
--SELECT * FROM @table
--DROP CONSTRAINT: SELECT \' ALTER TABLE [\' + ForeignKeyConstraintTableSchema + \'].[\' + ForeignKeyConstraintTableName + \'] DROP CONSTRAINT \' + ForeignKeyConstraintName + \'
GO\' FROM @table
--ADD CONSTRAINT: SELECT \' ALTER TABLE [\' + ForeignKeyConstraintTableSchema + \'].[\' + ForeignKeyConstraintTableName + \'] ADD CONSTRAINT \' + ForeignKeyConstraintName + \' FOREIGN KEY(\' + ForeignKeyConstraintColumnName + \') REFERENCES [\' + PrimaryKeyConstraintTableSchema + \'].[\' + PrimaryKeyConstraintTableName + \'](\' + PrimaryKeyConstraintColumnName + \')
GO\' FROM @table
GO
Amir Hussein Samiani, 26 February 2012 10:18
--Drop and Recreate Foreign Key Constraints
SET NOCOUNT ON
DECLARE @table TABLE( RowId INT PRIMARY KEY IDENTITY(1, 1), ForeignKeyConstraintName NVARCHAR(200), ForeignKeyConstraintTableSchema NVARCHAR(200), ForeignKeyConstraintTableName NVARCHAR(200), ForeignKeyConstraintColumnName NVARCHAR(200), PrimaryKeyConstraintName NVARCHAR(200), PrimaryKeyConstraintTableSchema NVARCHAR(200), PrimaryKeyConstraintTableName NVARCHAR(200), PrimaryKeyConstraintColumnName NVARCHAR(200) )
INSERT INTO @table(ForeignKeyConstraintName, ForeignKeyConstraintTableSchema, ForeignKeyConstraintTableName, ForeignKeyConstraintColumnName) SELECT U.CONSTRAINT_NAME, U.TABLE_SCHEMA, U.TABLE_NAME, U.COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE U INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C ON U.CONSTRAINT_NAME = C.CONSTRAINT_NAME WHERE C.CONSTRAINT_TYPE = \\\\\\\'FOREIGN KEY\\\\\\\'
UPDATE @table SET PrimaryKeyConstraintName = UNIQUE_CONSTRAINT_NAME FROM @table T INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R ON T.ForeignKeyConstraintName = R.CONSTRAINT_NAME
UPDATE @table SET PrimaryKeyConstraintTableSchema = TABLE_SCHEMA, PrimaryKeyConstraintTableName = TABLE_NAME FROM @table T INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C ON T.PrimaryKeyConstraintName = C.CONSTRAINT_NAME
UPDATE @table SET PrimaryKeyConstraintColumnName = COLUMN_NAME FROM @table T INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE U ON T.PrimaryKeyConstraintName = U.CONSTRAINT_NAME
--SELECT * FROM @table
--DROP CONSTRAINT: SELECT \\\\\\\' ALTER TABLE [\\\\\\\' + ForeignKeyConstraintTableSchema + \\\\\\\'].[\\\\\\\' + ForeignKeyConstraintTableName + \\\\\\\'] DROP CONSTRAINT \\\\\\\' + ForeignKeyConstraintName + \\\\\\\'
GO\\\\\\\' FROM @table
--ADD CONSTRAINT: SELECT \\\\\\\' ALTER TABLE [\\\\\\\' + ForeignKeyConstraintTableSchema + \\\\\\\'].[\\\\\\\' + ForeignKeyConstraintTableName + \\\\\\\'] ADD CONSTRAINT \\\\\\\' + ForeignKeyConstraintName + \\\\\\\' FOREIGN KEY(\\\\\\\' + ForeignKeyConstraintColumnName + \\\\\\\') REFERENCES [\\\\\\\' + PrimaryKeyConstraintTableSchema + \\\\\\\'].[\\\\\\\' + PrimaryKeyConstraintTableName + \\\\\\\'](\\\\\\\' + PrimaryKeyConstraintColumnName + \\\\\\\')
GO\\\\\\\' FROM @table
GO