Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Таблица с данни, съдържаща SqlGeometry, причинява неуспешно изпълнение на съхранена процедура... Защо?

Откакто направих кратък коментар по въпроса ви, имах възможност да си поиграя напълно с опциите. Изглежда, че в момента (дори да опитвате .NET 4.6 и SQL 2014) не можете да зададете SqlGeography ИЛИ SqlGeometry като typeof() параметър при дефиниране на колона за DataTable . За абсолютна яснота можете да го направите в .NET и дори да го попълните, но след това не можете да предадете тази таблица като TVP към съхранена процедура.

Има две опции.

Опция 1. Предайте стойността във формат WKT.

Определете вашия тип таблица, както следва.

CREATE TYPE [dbo].[WKT_Example] AS TABLE
(
    [geom] [varchar](max) NOT NULL
)

След това дефинирайте своята съхранена процедура, както следва.

CREATE PROCEDURE [dbo].[BulkInsertFromWKT]

    @rows [dbo].[WKT_Example] READONLY

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    INSERT INTO [dbo].[Table1]
        ([SpatialData])
    SELECT
        geometry::STGeomFromText(R.[SpatialData], 4326)
    FROM
        @rows R;

END

Дефинирайте вашата .NET DataTable по следния начин:

DataTable wktTable = new DataTable();
wktTable.Columns.Add("SpatialData", typeof(string));

Попълнете го, както следва:

for (int j = 0; j < geometryCollection.Count; j++)
{
    System.Data.SqlTypes.SqlString wkt = geometryCollection[j].STAsText().ToSqlString();

    wktTable.Rows.Add(wkt.ToString());
}

Опция 2. Предайте стойността във формат WKB.

Определете вашия тип таблица, както следва.

CREATE TYPE [dbo].[WKB_Example] AS TABLE
(
    [geom] [varbinary](max) NOT NULL
)

След това дефинирайте своята съхранена процедура, както следва.

CREATE PROCEDURE [dbo].[BulkInsertFromWKB]

    @rows [dbo].[WKB_Example] READONLY

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    INSERT INTO [dbo].[Table1]
        ([SpatialData])
    SELECT
        geometry::STGeomFromWKB(R.[SpatialData], 4326)
    FROM
        @rows R;

END

Дефинирайте вашата .NET DataTable по следния начин:

DataTable wkbTable = new DataTable();
wkbTable.Columns.Add("SpatialData", typeof(System.Data.SqlTypes.SqlBytes));

Попълнете го, както следва:

for (int j = 0; j < geometryCollection.Count; j++)
{
    wkbTable.Rows.Add(geographyCollection[j].STAsBinary());
}

Бележки:

Дефинирайте вашия SqlParameter както следва:

SqlParameter p = new SqlParameter("@rows", SqlDbType.Structured);
p.TypeName = "WKB_Example"; // The name of your table type
p.Value = wkbTable;

Оставил съм SRID от 4326 от работата си по география. Можете да промените това на каквото пожелаете - и наистина, ако използвате Geography Предлагам да го направите като втори параметър, за да имате гъвкавост.

Освен това, ако производителността е критична, ще откриете, че използването на WKB е по-добро. Моите тестове установиха, че WKB завърши за 45% до 65% от времето, необходимо за WKT. Това ще варира в зависимост от сложността на вашите данни и от вашата настройка.

Информацията, която сте намерили при указване на UdtTypeName на параметъра като "Геометрия" / "География" е правилно, когато вашата Съхранена процедура има параметър от тип [Геометрия] или [География]. Не се отнася за TVP.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. 2 начина за връщане на името на сървъра в SQL Server (T-SQL)

  2. Как да извлека този конкретен подниз в SQL Server?

  3. Създайте задание за агент на SQL Server с помощта на SSMS

  4. SQL Server:Как да изберете всички дни в диапазон от време, дори ако няма данни за няколко дни

  5. Поддържане на изчислена колона за дата и час в SQL Server 2005