如何将地理批量插入新的 sql server 2008 表

Posted

技术标签:

【中文标题】如何将地理批量插入新的 sql server 2008 表【英文标题】:How to bulk insert geography into a new sql server 2008 table 【发布时间】:2011-08-23 18:01:40 【问题描述】:

我有一个非常大的形状文件,其中包含数十万行多边形和其他相关数据,例如格式化的地址和 APN 编号。如何在不使用 Shape2SQL 之类的东西的情况下将这些数据放入带有地理的表中?我不能很好地为每一行运行插入语句,这将永远花费,最佳解决方案是创建一个 csv 或格式正确的 bin 文件,然后进行批量插入,或bcp,或 openrowset,但尝试,尝试,尝试,因为我可能无法让 csv 文件或 bin 文件工作。有人可以帮忙吗?

以下代码是我能做到的最好的。

SqlGeographyBuilder sql_geography_builder = new SqlGeographyBuilder();
sql_geography_builder.SetSrid(4326);
sql_geography_builder.BeginGeography(OpenGisGeographyType.Polygon);
sql_geography_builder.BeginFigure(-84.576064, 39.414853);
sql_geography_builder.AddLine(-84.576496, 39.414800);
sql_geography_builder.AddLine(-84.576522, 39.414932);
sql_geography_builder.AddLine(-84.576528, 39.414964);
sql_geography_builder.AddLine(-84.576095, 39.415015);
sql_geography_builder.AddLine(-84.576064, 39.414853);
sql_geography_builder.EndFigure();
sql_geography_builder.EndGeography();
SqlGeography sql_geography = new SqlGeography();
sql_geography = sql_geography_builder.ConstructedGeography;


FileStream file_stream = new FileStream("C:\\PROJECTS\\test.bin", FileMode.Create);
BinaryWriter binary_writer = new BinaryWriter(file_stream);

sql_geography.Write(binary_writer);
binary_writer.Flush();

binary_writer.Close();
file_stream.Close();
file_stream.Dispose();

SqlConnection sql_connection = new SqlConnection(connection_string);
sql_connection.Open();

SqlCommand sql_command = new SqlCommand();
sql_command.Connection = sql_connection;
sql_command.CommandTimeout = 0;
sql_command.CommandType = CommandType.Text;
sql_command.CommandText = "INSERT INTO [SPATIAL_TEST].[dbo].[Table_1] ([geo]) " +
              "SELECT [ors].* " +
              "FROM OPENROWSET(BULK 'C:\\PROJECTS\\AMP\\test.bin', SINGLE_BLOB) AS [ors] ";
sql_command.ExecuteNonQuery();

sql_command.Dispose();
sql_connection.Close();
sql_connection.Dispose();

但这只能让我单独导入多边形——我还需要其他所有东西。

【问题讨论】:

csv 文件根本不起作用,因为 ssis 不会接受 WFT 或 WFD 作为批量插入的有效字段。我唯一的希望是创建一个像这里看到的二进制数据文件(***.com/questions/282604/…),如果我只想导入地理,上面的代码效果很好。问题是我有更多的信息可以进入文件,而不仅仅是地理信息,我不知道如何构建我的二进制文件或我的格式文件,所以我可以做一个正确的 bcp 或 openrowset。 对于未来的读者来说,值得知道的是.NET中的SqlBulkCopy可以直接插入SqlGeography类型。在此处查看此 SO 答案:***.com/a/21128445 【参考方案1】:

好吧,经过几天的头痛,我得出了没有答案的结论。甚至强大的 ESRI 也没有任何线索。谢天谢地,我确实想出了一个不同的灵魂。在我的表定义中,我创建了一个 NVARCHAR(MAX) 列来保存我的地理位置的 WFT 并将该 WFT 添加到我的 csv 文件中,然后在批量插入之后我运行一个表范围的更新语句以将 WFT 转换为实际的地理类型.还要调整 csv 文件以使用除 a 之外的其他字符,以分隔,因为 WFT 包含 ,'s

SqlGeographyBuilder sql_geography_builder = new SqlGeographyBuilder();
sql_geography_builder.SetSrid(4326);
sql_geography_builder.BeginGeography(OpenGisGeographyType.Polygon);
sql_geography_builder.BeginFigure(-84.576064, 39.414853);
sql_geography_builder.AddLine(-84.576496, 39.414800);
sql_geography_builder.AddLine(-84.576522, 39.414932);
sql_geography_builder.AddLine(-84.576528, 39.414964);
sql_geography_builder.AddLine(-84.576095, 39.415015);
sql_geography_builder.AddLine(-84.576064, 39.414853);
sql_geography_builder.EndFigure();
sql_geography_builder.EndGeography();
SqlGeography sql_geography = new SqlGeography();
sql_geography = sql_geography_builder.ConstructedGeography;

StreamWriter stream_writer = new StreamWriter("C:\\PROJECTS\\AMP\\test.csv");
stream_writer.AutoFlush = true;
stream_writer.WriteLine("1?123 TEST AVE?" + sql_geography.ToString() + "?");
stream_writer.Flush();
stream_writer.WriteLine("2?456 TEST AVE?" + sql_geography.ToString() + "?");
stream_writer.Flush();
stream_writer.WriteLine("9?789 TEST AVE?" + sql_geography.ToString() + "?");
stream_writer.Flush();
stream_writer.Close();
stream_writer.Dispose();

SqlConnection sql_connection = new SqlConnection(STRING_SQL_CONNECTION);
sql_connection.Open();

SqlCommand sql_command = new SqlCommand();
sql_command.Connection = sql_connection;
sql_command.CommandTimeout = 0;
sql_command.CommandType = CommandType.Text;
sql_command.CommandText = "BULK INSERT [SPATIAL_TEST].[dbo].[Table_1] " +
                          "FROM 'C:\\PROJECTS\\AMP\\test.csv' " +
                          "WITH (FIELDTERMINATOR = '?', ROWTERMINATOR = '\n') " +
                          "" +
                          "UPDATE [SPATIAL_TEST].[dbo].[Table_1] " +
                          "SET [geo] = geography::STPolyFromText([geo_string], 4326) ";
sql_command.ExecuteNonQuery();

sql_command.Dispose();
sql_connection.Close();
sql_connection.Dispose();

MessageBox.Show("DONE");

catch (Exception ex)
 MessageBox.Show(ex.Message); 

【讨论】:

以上是关于如何将地理批量插入新的 sql server 2008 表的主要内容,如果未能解决你的问题,请参考以下文章

JPA SQL Server 批量插入

使用 pymssql 将文本文件批量插入 SQL Server

尝试将数据表批量插入 SQL Server 时出现 InvalidOperationException

如何使用SQL Server中的DataTable模拟“批量”插入

Sqoop 导出到 Sql Server VS 批量插入到 SQL Server

批量插入、SQL Server 2000、unix 换行符