Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Tablica danych zawierająca SqlGeometry powoduje niepowodzenie wykonywania procedury składowanej... Dlaczego?

Odkąd skomentowałem twoje pytanie, miałem okazję w pełni pobawić się opcjami. Wygląda na to, że obecnie (nawet próbując .NET 4.6 i SQL 2014) nie można ustawić SqlGeography LUB SqlGeometry jako typeof() parametr podczas definiowania kolumny dla DataTable . Aby uzyskać absolutną przejrzystość, możesz to zrobić w .NET, a nawet wypełnić ją, ale wtedy nie możesz przekazać tej tabeli jako TVP do procedury przechowywanej.

Istnieją dwie opcje.

Opcja 1. Przekaż wartość w formacie WKT.

Zdefiniuj typ tabeli w następujący sposób.

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

Następnie zdefiniuj procedurę składowaną w następujący sposób.

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

Zdefiniuj swoją tabelę danych .NET w następujący sposób:

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

Wypełnij go w następujący sposób:

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

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

Opcja 2. Przekaż wartość w formacie WKB.

Zdefiniuj typ tabeli w następujący sposób.

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

Następnie zdefiniuj procedurę składowaną w następujący sposób.

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

Zdefiniuj swoją tabelę danych .NET w następujący sposób:

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

Wypełnij go w następujący sposób:

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

Uwagi:

Zdefiniuj swój SqlParameter w następujący sposób:

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

Zostawiłem SRID 4326 w mojej pracy z geografii. Możesz to zmienić na co chcesz - i rzeczywiście, jeśli używasz Geography Sugerowałbym, aby był to drugi parametr, aby zapewnić elastyczność.

Dodatkowo, jeśli wydajność jest krytyczna, lepiej będzie używać WKB. Moje testy wykazały, że WKB ukończono w 45% do 65% czasu, jaki zajęło WKT. Zależy to od złożoności danych i konfiguracji.

Informacje znalezione podczas określania parametru UdtTypeName jako „Geometria” / „Geografia” jest poprawna, gdy procedura składowana ma parametr typu [Geometry] lub [Geography]. Nie dotyczy to 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. UDT jako parametr w zapytaniu EF4

  2. Jak włączyć kompresję w istniejącej tabeli w SQL Server (T-SQL)

  3. SQL Server nie zwalnia pamięci po wykonaniu zapytania

  4. Zapytanie SQL Server, które identyfikuje brakujące dane dla określonych dat

  5. Jak działa klauzula DISTINCT języka SQL?