SqlServer 獲取 當前地址下 所有數據庫字段信息 / 快速 批量插入數據庫(TVPs)

全網獨一份 !!!

純手工嘔心瀝血之作!!!


SQL執行


--拼裝 當前地址下 所有數據庫字段信息
BEGIN

DECLARE @dataBaseName NVARCHAR(MAX)--數據庫名稱
DECLARE @tableName NVARCHAR(MAX )--表名
DECLARE @sql NVARCHAR(MAX)--將要執行的sql

--判斷是否存在,存在則刪除臨時表
IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE id = object_id(N'tempdb..##myParentTable') and type='U')
   DROP TABLE ##myParentTable

IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE id = object_id(N'tempdb..##myChildTable') and type='U')
   DROP TABLE ##myChildTable

--創建myParentTable臨時表(存儲 該地址下 所有表名)
--(存數據庫名稱和表名,數據不多,表有多少,數據有多少)
CREATE TABLE ##myParentTable
(
  序號 INT IDENTITY(1,1),
  數據庫名稱 NVARCHAR(MAX),
  表名 NVARCHAR(MAX)  
)

--創建myChildTable臨時表
--(存儲字段相關的信息,字段有多少個,數據就有多少,數據龐大,需要耐心等待) 據測試 1分鐘左右 1萬多條數據
CREATE TABLE ##myChildTable
(
  序號 INT  IDENTITY(1,1),
  數據庫名稱 NVARCHAR(MAX),
  表名 NVARCHAR(MAX),
  列名 NVARCHAR(MAX),
  列說明 NVARCHAR(MAX),
  數據類型 NVARCHAR(MAX),
  長度 INT,
  小數位數 INT,
  標識 NVARCHAR(MAX ),
  主鍵 NVARCHAR(MAX ),
  允許空 NVARCHAR(MAX ),
  默認值 NVARCHAR(MAX )   
)


--聲明 Parent_Cursor 遊標   (格式:DECLARE 遊標名稱 For 數據) (數據庫名稱)
 DECLARE Parent_Cursor CURSOR   FOR
   SELECT name FROM sysdatabases WHERE name NOT IN('master','tempdb','model','msdb')   --查詢所有的數據庫名稱(排除系統數據庫)

    --打開遊標--
    OPEN Parent_Cursor

    --開始循環遊標變量(格式:)
    FETCH NEXT FROM Parent_Cursor INTO @dataBaseName
     WHILE @@FETCH_STATUS = 0    --返回被 FETCH語句執行的最後遊標的狀態--
       BEGIN           

            SET @sql=' USE '+@dataBaseName+';';
            SET @sql=@sql+'insert ##myParentTable (數據庫名稱,表名) (select'''+@dataBaseName+''', name from sysobjects where xtype=''U''); ';
            EXEC(@sql)      

            FETCH NEXT FROM Parent_Cursor INTO @dataBaseName   --轉到下一個遊標,沒有會死循環
        END    
        CLOSE Parent_Cursor  --關閉遊標
    DEALLOCATE Parent_Cursor   --釋放遊標    


----------------------------------------------------------------------------

    --聲明遊標 Child_Cursor   (數據庫名稱, 表名)
    DECLARE Child_Cursor CURSOR FOR    
                SELECT 數據庫名稱, 表名 from ##myParentTable

      --打開遊標--
    OPEN Child_Cursor
    --開始循環遊標變量--
    FETCH NEXT FROM Child_Cursor INTO @dataBaseName,@tableName
     WHILE @@FETCH_STATUS = 0    --返回被 FETCH語句執行的最後遊標的狀態--
       BEGIN       

      SET @sql=' USE '+@dataBaseName+';';    
      SET @sql=@sql+'INSERT INTO ##myChildTable (數據庫名稱,表名,列名,列說明,數據類型,長度,小數位數,標識,主鍵,允許空,默認值)(
            SELECT 
            '''+@dataBaseName+''',
            '''+@tableName+''',
            col.name AS 列名 ,
            CONVERT(NVARCHAR(max),ISNULL(ep.[value], '''')) AS 列說明 ,
            t.name AS 數據類型 ,
            col.length AS 長度 ,
            ISNULL(COLUMNPROPERTY(col.id, col.name, ''Scale''), 0) AS 小數位數 ,
            CASE WHEN COLUMNPROPERTY(col.id, col.name, ''IsIdentity'') = 1 THEN ''√''
            ELSE ''''
            END AS 標識 ,
            CASE WHEN EXISTS ( SELECT 1
            FROM dbo.sysindexes si
            INNER JOIN dbo.sysindexkeys sik ON si.id = sik.id
            AND si.indid = sik.indid
            INNER JOIN dbo.syscolumns sc ON sc.id = sik.id
            AND sc.colid = sik.colid
            INNER JOIN dbo.sysobjects so ON so.name = si.name
            AND so.xtype = ''PK''
            WHERE sc.id = col.id
            AND sc.colid = col.colid ) THEN ''√''
            ELSE ''''
            END AS 主鍵 ,
            CASE WHEN col.isnullable = 1 THEN ''√''
            ELSE ''''
            END AS 允許空 ,
            ISNULL(comm.text, '''') AS 默認值
            FROM dbo.syscolumns col
            LEFT JOIN dbo.systypes t ON col.xtype = t.xusertype
            inner JOIN dbo.sysobjects obj ON col.id = obj.id
            AND obj.xtype = ''U''
            AND obj.status >= 0
            LEFT JOIN dbo.syscomments comm ON col.cdefault = comm.id
            LEFT JOIN sys.extended_properties ep ON col.id = ep.major_id
            AND col.colid = ep.minor_id
            AND ep.name = ''MS_Description''
            LEFT JOIN sys.extended_properties epTwo ON obj.id = epTwo.major_id
            AND epTwo.minor_id = 0
            AND epTwo.name = ''MS_Description''
            WHERE obj.name = '''+@tableName +'''
 )'; 

       EXEC(@sql)   --執行sql

            FETCH NEXT FROM Child_Cursor INTO @dataBaseName,@tableName   --轉到下一個遊標,沒有會死循環

        END     
        CLOSE Child_Cursor  --關閉遊標
    DEALLOCATE Child_Cursor   --釋放遊標    

END
GO 
--end

--查看獲得的數量
 SELECT COUNT(1) FROM ##myChildTable

--經測試 :  224秒  得到  17700 條 字段信息

--查看最終數據
SELECT TOP 1000 * FROM ##myChildTable

--檢測臨時表是否存在
IF EXISTS (SELECT * FROM tempdb..sysobjects WHERE id=object_id(N'tempdb..##myChildTable'))
PRINT '存在'
ELSE 
PRINT '不存在'


Main方法代碼

namespace ConsoleApp3
{
    class Program
    {
        static void Main(string[] args)
        {
            //數據庫鏈接Model
            SqlQueryModel model =new SqlQueryModel();

            #region 查數據

            //源數據地址
            model = new SqlQueryModel()
            {
                Ip = "輸入對應ip地址",
                DataBase = "tempdb",//本次查數據隨意指定一個數據庫就可以.無影響
                UserName = "賬號",
                UserPwd = "密碼"
            };
            //配置連接字符串
            SqlHelper sqlHelper = new SqlHelper(model);

            //查全局臨時表.(這個表咱們需要的所有數據)
            var myTable = sqlHelper.GetTable("SELECT * FROM ##myChildTable", System.Data.CommandType.Text, null);

            #endregion

            #region 存數據

            //目標數據地址
            model = new SqlQueryModel()
            {
                Ip = ".",
                DataBase = "MyDBInfo",//這次的數據庫名稱很重要.對應着數據存放地址
                UserName = "sa",
                UserPwd = "sa123"
            };
            //配置數據庫鏈接
            sqlHelper = new SqlHelper(model);

            //執行數據TVPs批量插入
            sqlHelper.TbaleValuedToDb(myTable);

            #endregion

        }
    }
}

SqlHelper

using System;
using System.Data;
using System.Data.SqlClient;

namespace ConsoleApp3
{
    public class SqlQueryModel
    {
        public string Ip { get; set; }
        public string DataBase { get; set; }
        public string UserName { get; set; }
        public string UserPwd { get; set; }
        public string SqlStr { get; set; }
    }
    public class SqlHelper
    {
        /// <summary>
        /// sqlhelper
        /// xuejie
        /// 2018-07-17
        /// </summary>
        private  string connStr = string.Empty;

        public  SqlHelper(SqlQueryModel model)
        {
            connStr = $"Data Source={model.Ip}; Initial Catalog={model.DataBase}; User ID={model.UserName}; Password={model.UserPwd};";
        }

        /// <summary>
        /// 返回table
        /// </summary>
        /// <param name="sql">SQL語句</param>
        /// <param name="type">參數化類型</param>
        /// <param name="pars">SqlParameter數組</param>
        /// <returns></returns>
        public  DataTable GetTable(string sql, CommandType type, params SqlParameter[] pars)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connStr))
                {
                    using (SqlDataAdapter atper = new SqlDataAdapter(sql, conn))
                    {
                        atper.SelectCommand.CommandType = type;
                        if (pars != null)
                        {
                            atper.SelectCommand.Parameters.AddRange(pars);
                        }
                        DataTable da = new DataTable();
                        atper.Fill(da);
                        return da;
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        #region [ 使用TVPs插入數據 ]

        /// <summary>
        /// 使用TVPs插入數據( 經測試  1萬7千條數據需要 10s )
        /// </summary>
        /// <param name="dt">數據</param>
        public void TbaleValuedToDb(DataTable dt)
        {

            /*
                DROP TYPE BulkUdt --刪除自定義表類型

                --注意 首先需要手動在對應的數據庫中 創建一個自定義表類型. 在SqlServer裏 執行 下面這段代碼

                -- 創建一個 名稱爲 BulkUdt 的 自定義表類型
                CREATE TYPE BulkUdt AS TABLE  
                (
                  序號 int ,
                  數據庫名稱 NVARCHAR(MAX),
                  表名 nvarchar(max),
                  列名 NVARCHAR(max),
                  列說明 NVARCHAR(MAX ),
                  數據類型 NVARCHAR(MAX ),
                  長度 INT,
                  小數位數 INT,
                  標識 NVARCHAR(MAX ),
                  主鍵 NVARCHAR(MAX ),
                  允許空 NVARCHAR(MAX ),
                  默認值 NVARCHAR(MAX )   
                ) 

             */



            SqlConnection sqlconn = new SqlConnection(connStr);
            string sqlStatement =
                //指定數據庫名稱
                "insert into 數據庫名字 " +

                //指定數據庫字段 (如果全部需要插入可以寫成 * 號)
                "(序號,數據庫名稱,表名,列名,列說明,數據類型,長度,小數位數,標識,主鍵,允許空,默認值)" +

                //指定 自定義表類型的字段名稱 (如果需要全部插入 可以寫成 * 號)
                " SELECT nc.序號,nc.數據庫名稱,nc.表名,nc.列名,nc.列說明,nc.數據類型,nc.長度,nc.小數位數,nc.標識,nc.主鍵,nc.允許空,nc.默認值 " + 
                " FROM @TableData AS nc";

            SqlCommand cmd = new SqlCommand(sqlStatement, sqlconn);
            SqlParameter catParam = cmd.Parameters.AddWithValue("@TableData", dt);//傳入dataTable數據
            catParam.SqlDbType = SqlDbType.Structured;

            //指定類型爲 自定義表類型的名稱
            catParam.TypeName = "dbo.BulkUdt";

            try
            {
                sqlconn.Open();
                if (dt != null && dt.Rows.Count != 0)
                {
                    //執行sql 返回受影響行數
                    cmd.ExecuteNonQuery();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                sqlconn.Close();
            }


            /*

                --Profiler 監測到 最後數據庫執行的 sql

                declare @p3 dbo.BulkUdt

                insert into @p3 values(1,N'master',N'trace_xe_action_map',N'trace_column_id',N'',N'smallint',2,0,N'',N'',N'',N'')
                insert into @p3 values(2,N'master',N'trace_xe_action_map',N'package_name',N'',N'nvarchar',120,0,N'',N'',N'',N'')
                insert into @p3 values(3,N'master',N'trace_xe_action_map',N'xe_action_name',N'',N'nvarchar',120,0,N'',N'',N'',N'')
                insert into @p3 values(4,N'master',N'trace_xe_event_map',N'trace_event_id',N'',N'smallint',2,0,N'',N'',N'',N'')
                insert into @p3 values(5,N'master',N'trace_xe_event_map',N'package_name',N'',N'nvarchar',120,0,N'',N'',N'',N'')
                ...
                ...
                ...

                exec sp_executesql N'insert into 數據庫名字

                (序號,數據庫名稱,表名,列名,列說明,數據類型,長度,小數位數,標識,主鍵,允許空,默認值) 

                SELECT nc.序號,nc.數據庫名稱,nc.表名,nc.列名,nc.列說明,nc.數據類型,nc.長度,nc.小數位數,nc.標識,nc.主鍵,nc.允許空,nc.默認值  

                FROM @TableData AS nc',N'@TableData [dbo].[BulkUdt] READONLY',@TableData=@p3


             */

        }

        #endregion

    }
}

本地數據庫字段

這裏寫圖片描述

效果展示

這裏寫圖片描述

把這些字段信息 存到自己的 本地數據庫
以後有需要的時候 直接條件查詢.
就可以查看到這個字段的所有信息了.

大家也可以ctrl +A 全選後 鼠標右鍵. 有 “將結果另存爲” .
保存的類型就選擇 .csv 就可以用 excel 打開. 或者 全選後 選擇 ” 連同標題一起復制 “,
然後粘貼到 excel. 以後在excel中也可以 搜索.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章