99using System . Reflection ;
1010using System . Text ;
1111using System . Windows . Forms ;
12+ using DBADashGUI . SchemaCompare ;
13+ using System . Globalization ;
1214
1315namespace DBADashGUI . CustomReports
1416{
@@ -37,7 +39,11 @@ private ToolStripMenuItem GetSaveTableMenuItem()
3739 new ToolStripMenuItem ( "From Data Table" , Properties . Resources . DataTable_16x ,
3840 ( _ , _ ) => SaveTable ( false ) ) { ToolTipText = "Save underlying DataTable to table in SQL Server database" } ,
3941 new ToolStripMenuItem ( "From Grid" , Properties . Resources . Table_16x ,
40- ( _ , _ ) => SaveTable ( true ) ) { ToolTipText = "Save grid to table in SQL Server database" }
42+ ( _ , _ ) => SaveTable ( true ) ) { ToolTipText = "Save grid to table in SQL Server database" } ,
43+ new ToolStripMenuItem ( "Script Data Table" , Properties . Resources . SQLScript_16x ,
44+ ( _ , _ ) => ScriptTable ( false ) ) { ToolTipText = "Script underlying DataTable AS INSERT" } ,
45+ new ToolStripMenuItem ( "Script Grid" , Properties . Resources . TableScript_16x ,
46+ ( _ , _ ) => ScriptTable ( true ) ) { ToolTipText = "Script grid as INSERT" }
4147 } ) ;
4248 return tsSave ;
4349 }
@@ -482,9 +488,10 @@ private DataTable GetDataTableForExport(bool fromGrid)
482488 /// <param name="dataTable">The DataTable containing the schema to generate the CREATE TABLE command.</param>
483489 /// <param name="tableName">The name of the table to be created.</param>
484490 /// <returns>A string containing the SQL CREATE TABLE command.</returns>
485- private static string GenerateCreateTableCommand ( DataTable dataTable , string tableName )
491+ private static string GenerateCreateTableCommand ( DataTable dataTable , string tableName , bool quoteTableName = true )
486492 {
487- var commandText = new StringBuilder ( $ "CREATE TABLE { tableName . SqlQuoteName ( ) } (") ;
493+ var quotedTableName = quoteTableName ? tableName . SqlQuoteName ( ) : tableName ;
494+ var commandText = new StringBuilder ( $ "CREATE TABLE { quotedTableName } (\n \t ") ;
488495
489496 for ( var i = 0 ; i < dataTable . Columns . Count ; i ++ )
490497 {
@@ -505,11 +512,11 @@ private static string GenerateCreateTableCommand(DataTable dataTable, string tab
505512
506513 if ( i < dataTable . Columns . Count - 1 )
507514 {
508- commandText . Append ( ", " ) ;
515+ commandText . Append ( ",\n \t " ) ;
509516 }
510517 }
511518
512- commandText . Append ( ");" ) ;
519+ commandText . Append ( "\n );" ) ;
513520
514521 return commandText . ToString ( ) ;
515522 }
@@ -522,8 +529,8 @@ private static string GenerateCreateTableCommand(DataTable dataTable, string tab
522529 private static string ConvertToSqlType ( DataColumn column )
523530 {
524531 var columnSize = column . MaxLength ; // Note: Not set using DataAdapter Fill method, so types will end up being MAX
525- const int numericPrecision = 18 ;
526- const int numericScale = 0 ;
532+ const int numericPrecision = 28 ;
533+ const int numericScale = 9 ;
527534
528535 return column . DataType switch
529536 {
@@ -665,5 +672,112 @@ public DataTable DataGridViewToDataTable(DataGridView dgv)
665672
666673 return dt ;
667674 }
675+
676+ // / <summary>
677+ // / Script DataGridView AS INSERT statements
678+ // / </summary>
679+ // / <param name="fromGrid">If true, saves the DataGridView to a table. If false, saves the underlying DataTable to a table.</param>
680+ private void ScriptTable ( bool fromGrid )
681+ {
682+ const string tableName = "#DBADashGrid" ;
683+ try
684+ {
685+ var dt = GetDataTableForExport ( fromGrid ) ;
686+ var tableScript = GenerateCreateTableCommand ( dt , tableName , false ) ;
687+ var insertStatements = GenerateInsertStatementsWithBatching ( dt , tableName , false ) ;
688+ var header = @$ "/*********************************************************
689+ ----------------------------------------------------------
690+ | ____ ____ _ ____ _ |
691+ | | _ \ | __ ) / \ | _ \ __ _ ___ | |__ |
692+ | | | | || _ \ / _ \ | | | | / _` |/ __|| '_ \ |
693+ | | |_| || |_) |/ ___ \ | |_| || (_| |\__ \| | | | |
694+ | |____/ |____//_/ \_\ |____/ \__,_||___/|_| |_| |
695+ | |
696+ | SQL Server Monitoring by David Wiseman |
697+ | Copyright 2022 Trimble, Inc. |
698+ | https://dbadash.com |
699+ | https://github.com/trimble-oss/dba-dash |
700+ | Generated: { DateTime . Now : yyyy-MM-dd HH:mm:ss} |
701+ ----------------------------------------------------------
702+ *********************************************************/
703+
704+ IF OBJECT_ID('tempdb..{ tableName } ') IS NOT NULL
705+ BEGIN
706+ DROP TABLE { tableName }
707+ END
708+ GO
709+ " ;
710+ var footer = $ "\n \n SELECT { GetColumnList ( dt ) } \n FROM { tableName } \n \n --DROP TABLE { tableName } ";
711+ var insertScript = header + tableScript + "\n " + string . Join ( "\n " , insertStatements ) + footer ;
712+ var frm = new CodeViewer ( ) { Code = insertScript , Language = CodeEditor . CodeEditorModes . SQL } ;
713+ frm . ShowDialog ( ) ;
714+ }
715+ catch ( Exception ex )
716+ {
717+ MessageBox . Show ( "Error generating script: " + ex . Message , "Error" , MessageBoxButtons . OK ,
718+ MessageBoxIcon . Error ) ;
719+ }
720+ }
721+
722+ public static List < string > GenerateInsertStatementsWithBatching ( DataTable dataTable , string tableName , bool quoteTableName = true )
723+ {
724+ const int batchSize = 1000 ;
725+ var insertStatements = new List < string > ( ) ;
726+ var totalRows = dataTable . Rows . Count ;
727+ var batchCount = ( int ) Math . Ceiling ( totalRows / ( double ) batchSize ) ;
728+ var quotedTableName = quoteTableName ? tableName . SqlQuoteName ( ) : tableName ;
729+ for ( var batchIndex = 0 ; batchIndex < batchCount ; batchIndex ++ )
730+ {
731+ var batchRows = dataTable . AsEnumerable ( ) . Skip ( batchIndex * batchSize ) . Take ( batchSize ) ;
732+ var valuesList = batchRows . Select ( row => string . Join ( ", " , row . ItemArray . Select ( ( value , index ) => FormatSqlValue ( value , dataTable . Columns [ index ] ) ) ) ) . Select ( rowValues => $ "({ rowValues } )") . ToList ( ) ;
733+
734+ var columnNames = GetColumnList ( dataTable ) ;
735+ var valuesClause = string . Join ( ",\n " , valuesList ) ;
736+ var insertStatement = $ "INSERT INTO { quotedTableName } (\n \t { columnNames } )\n VALUES { valuesClause } ;";
737+ insertStatements . Add ( insertStatement ) ;
738+ }
739+
740+ return insertStatements ;
741+ }
742+
743+ private static string GetColumnList ( DataTable dataTable ) => string . Join ( ", \n \t " , dataTable . Columns . Cast < DataColumn > ( ) . Select ( c => c . ColumnName . SqlQuoteName ( ) ) ) ;
744+
745+ /// <summary>
746+ /// Formats a value for use in a SQL statement.
747+ /// </summary>
748+ private static string FormatSqlValue ( object value , DataColumn column )
749+ {
750+ if ( value == DBNull . Value )
751+ {
752+ return "NULL" ;
753+ }
754+ else if ( column . DataType == typeof ( string ) )
755+ {
756+ return value . ToString ( ) . SqlSingleQuoteWithEncapsulation ( ) ;
757+ }
758+ else if ( column . DataType == typeof ( DateTime ) )
759+ {
760+ return ( ( DateTime ) value ) . ToString ( "yyyy-MM-dd HH:mm:ss.fff" ) . SqlSingleQuoteWithEncapsulation ( ) ;
761+ }
762+ else if ( column . DataType == typeof ( bool ) )
763+ {
764+ return ( bool ) value ? "1" : "0" ;
765+ }
766+ else if ( column . DataType == typeof ( byte [ ] ) )
767+ {
768+ // Convert byte array to hexadecimal string
769+ var byteArray = ( byte [ ] ) value ;
770+ var hexString = "0x" + BitConverter . ToString ( byteArray ) . Replace ( "-" , "" ) ;
771+ return hexString ;
772+ }
773+ else if ( column . DataType == typeof ( int ) || column . DataType == typeof ( long ) || column . DataType == typeof ( short ) || column . DataType == typeof ( byte ) || column . DataType == typeof ( decimal ) || column . DataType == typeof ( float ) || column . DataType == typeof ( double ) )
774+ {
775+ return Convert . ToString ( value , CultureInfo . InvariantCulture ) ;
776+ }
777+ else
778+ {
779+ return value . ToString ( ) . SqlSingleQuoteWithEncapsulation ( ) ;
780+ }
781+ }
668782 }
669783}
0 commit comments