STAsText: примеры (SQL)

Функция STAsText для работы с пространственными данными
Раздел: Функции для работы с пространственными данными, Пространственные
STAsText: nvarchar(max)

Функция STAsText в MS SQL Server

Функция STAsText является методом для экземпляров пространственных данных (geometry и geography) в SQL Server. Она возвращает представление экземпляра в формате WKT (Well-Known Text) открытого геопространционного консорциума (OGC).

Функция используется, когда необходимо получить текстовое, читаемое человеком описание геометрического объекта для отладки, логирования или передачи в системы, поддерживающие формат WKT.

Синтаксис и аргументы

Синтаксис метода: .STAsText ( )

Метод не принимает аргументов. Он вызывается для конкретного экземпляра пространственного типа данных (geometry или geography).

Возвращаемое значение

Тип возвращаемого значения: nvarchar(max)

Метод возвращает текстовое описание объекта. Для пустого экземпляра возвращается строка 'EMPTY'. Для экземпляра, не инициализированного с помощью метода STGeomFromText, может возвращаться NULL.

Формат WKT:
- Точка: POINT (X Y)
- Линия: LINESTRING (X1 Y1, X2 Y2, ...)
- Полигон: POLYGON ((X1 Y1, X2 Y2, ..., X1 Y1))
- Мультиточка: MULTIPOINT ((X1 Y1), (X2 Y2))
- Мультилиния: MULTILINESTRING ((...), (...))
- Мультиполигон: MULTIPOLYGON (((...)), ((...)))
- Коллекция: GEOMETRYCOLLECTION (POINT(...), LINESTRING(...))

Простые примеры использования STAsText

Пример 1: Точка (Point)

DECLARE @g geometry = geometry::STGeomFromText('POINT (10 20)', 0);
SELECT @g.STAsText() AS WKT_Result;
WKT_Result
POINT (10 20)

Пример 2: Линия (LineString)

DECLARE @g geometry;
SET @g = geometry::STGeomFromText('LINESTRING (0 0, 10 10, 20 5)', 4326);
SELECT @g.STAsText() AS LineString_WKT;
LineString_WKT
LINESTRING (0 0, 10 10, 20 5)

Пример 3: Полигон (Polygon)

DECLARE @g geometry = geometry::Parse('POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))');
SELECT @g.STAsText() AS Polygon_WKT;
Polygon_WKT
POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))

Пример 4: Пустой объект (Empty)

DECLARE @g geometry = geometry::STGeomFromText('POINT EMPTY', 0);
SELECT @g.STAsText() AS Empty_WKT;
Empty_WKT
EMPTY

Пример 5: Тип geography

DECLARE @g geography = geography::STGeomFromText('POINT(-122.359 47.651)', 4326);
SELECT @g.STAsText() AS Geog_WKT;
Geog_WKT
POINT (-122.359 47.651)

Похожие функции в MS SQL Server

ToString()

Метод .ToString() возвращает то же текстовое представление, что и STAsText(), но в формате, совместимом с более ранними версиями SQL Server. Функционально аналогичен для вывода WKT. Использование предпочтительно в сценариях обратной совместимости.

DECLARE @g geometry = geometry::STPointFromText('POINT(5 7)', 0);
SELECT @g.ToString() AS StringResult;
StringResult
POINT (5 7)

STGeometryType()

Метод .STGeometryType() возвращает не координаты, а имя типа геометрического объекта (например, 'Point', 'LineString'). Полезен для определения типа объекта перед его обработкой.

DECLARE @g geometry = geometry::STGeomFromText('LINESTRING(0 0, 1 1)', 0);
SELECT @g.STGeometryType() AS GeoType;
GeoType
LineString

AsTextZM()

Метод .AsTextZM() возвращает представление в формате WKT с учетом значений Z (высота) и M (мера), если они присутствуют в данных. STAsText() эти значения игнорирует. Использование предпочтительно для объектов с 3D или 4D координатами.

DECLARE @g geometry = geometry::Parse('POINT(1 2 3 4)');
SELECT @g.AsTextZM() AS ZM_Text,
       @g.STAsText() AS Standard_Text;
ZM_Text          Standard_Text
POINT (1 2 3 4) POINT (1 2)

Аналоги функции в других СУБД и языках

PostgreSQL/PostGIS

Функция ST_AsText(geometry) возвращает WKT представление. Аналогична SQL Server. Используется с типом данных GEOMETRY.

SELECT ST_AsText(ST_GeomFromText('POINT(10 20)'));
st_astext
POINT(10 20)

MySQL

Функция ST_AsText(g) возвращает WKT строку. Для spatial типов, таких как Point, LineString.

SELECT ST_AsText(ST_GeomFromText('POINT(15 30)'));
ST_AsText(ST_GeomFromText('POINT(15 30)'))
POINT(15 30)

Oracle Spatial

Метод SDO_UTIL.TO_WKTGEOMETRY(sdo_geometry) возвращает WKT. В более новых версиях также используется GET_WKT(). Отличается более сложной моделью данных SDO_GEOMETRY.

SELECT SDO_UTIL.TO_WKTGEOMETRY(SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(10, 20, NULL), NULL, NULL)) AS WKT FROM DUAL;
WKT
POINT (10.0 20.0)

SQLite с расширением SpatiaLite

Функция AsText(geometry) возвращает WKT представление.

SELECT AsText(MakePoint(10, 20));
AsText(MakePoint(10, 20))
POINT(10 20)

Python (библиотека Shapely)

Свойство .wkt объекта геометрии возвращает WKT строку.

from shapely.geometry import Point
p = Point(10, 20)
print(p.wkt)
POINT (10 20)

Типичные ошибки при использовании STAsText

Вызов для NULL экземпляра

Если переменная пространственного типа равна NULL, вызов метода STAsText() вернет NULL, а не ошибку.

DECLARE @g geometry;
SELECT @g.STAsText() AS Result;
Result
NULL

Неправильный формат исходных данных

Ошибка возникает на этапе создания объекта, а не при вызове STAsText(). Метод требует валидный геометрический объект.

DECLARE @g geometry;
SET @g = geometry::STGeomFromText('NOTAGEOMETRY (10 20)', 0); -- Ошибка парсинга
SELECT @g.STAsText();
Сообщение 6522, уровень 16...
Неправильный тип данных geometry...

Путаница между geometry и geography

Метод работает для обоих типов, но важно понимать разницу в семантике координат (плоскость vs сфера).

DECLARE @geo geography = geography::Point(47.651, -122.359, 4326);
SELECT @geo.STAsText() AS WKT; -- Координаты в порядке долгота/широта
WKT
POINT (-122.359 47.651)

Изменения в функции

Функция STAsText была введена в SQL Server 2008 вместе с поддержкой пространственных данных. С тех пор ее основная функциональность не претерпела значительных изменений.

В SQL Server 2012 и более поздних версиях улучшена общая производительность пространственных типов данных, что косвенно могло повлиять и на скорость работы этого метода.

Важное уточнение: начиная с SQL Server 2012, для получения WKT-представления с координатами Z и M рекомендуется использовать метод AsTextZM(), так как STAsText() продолжает возвращать только двумерные координаты (X, Y), игнорируя дополнительные измерения, если они есть.

Расширенные примеры использования

Пример 1: Работа с коллекцией объектов

Пример sql
DECLARE @col geometry = geometry::STGeomFromText('GEOMETRYCOLLECTION(POINT(1 2), LINESTRING(3 4, 5 6))', 0);
SELECT @col.STAsText() AS Collection_WKT,
       @col.STNumGeometries() AS Num_Geoms;
Collection_WKT
GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6))
Num_Geoms
2

Пример 2: Извлечение и анализ отдельных частей мультиполигона

Пример sql
DECLARE @mp geometry = geometry::STGeomFromText('MULTIPOLYGON (((0 0, 5 0, 5 5, 0 5, 0 0)), ((10 10, 15 10, 15 15, 10 15, 10 10)))', 0);
SELECT @mp.STGeometryN(1).STAsText() AS First_Polygon,
       @mp.STGeometryN(2).STAsText() AS Second_Polygon,
       @mp.STArea() AS Total_Area;
First_Polygon
POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))
Second_Polygon
POLYGON ((10 10, 15 10, 15 15, 10 15, 10 10))
Total_Area
50

Пример 3: Преобразование между типами geometry и geography с сохранением WKT

Пример sql
DECLARE @g_geom geometry = geometry::STGeomFromText('POINT(10 20)', 4326);
DECLARE @g_geog geography = geography::STGeomFromText(@g_geom.STAsText(), 4326);
SELECT @g_geom.STAsText() AS Geom_WKT,
       @g_geog.STAsText() AS Geog_WKT,
       @g_geog.Lat AS Latitude,
       @g_geog.Long AS Longitude;
Geom_WKT
POINT (10 20)
Geog_WKT
POINT (10 20)
Latitude
20
Longitude
10

Пример 4: Использование в табличном запросе для сериализации

Пример sql
CREATE TABLE #SpatialData (id INT, geom geometry);
INSERT INTO #SpatialData VALUES
(1, geometry::Point(0, 0, 0)),
(2, geometry::STGeomFromText('LINESTRING(1 1, 2 2)', 0)),
(3, geometry::Parse('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))'));

SELECT id, geom.STAsText() AS WKT_Representation
FROM #SpatialData
ORDER BY id;

DROP TABLE #SpatialData;
id  WKT_Representation
1   POINT (0 0)
2   LINESTRING (1 1, 2 2)
3   POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))

Пример 5: Сравнение объектов через их текстовое представление

Пример sql
DECLARE @g1 geometry = geometry::STGeomFromText('POINT(5 5)', 0);
DECLARE @g2 geometry = geometry::Point(5, 5, 0);
DECLARE @g3 geometry = geometry::STGeomFromText('POINT(5 6)', 0);

SELECT @g1.STAsText() AS g1_WKT,
       @g2.STAsText() AS g2_WKT,
       CASE WHEN @g1.STEquals(@g2) = 1 THEN 'Equal' ELSE 'Not Equal' END AS Compare_1_2,
       @g3.STAsText() AS g3_WKT,
       CASE WHEN @g1.STEquals(@g3) = 1 THEN 'Equal' ELSE 'Not Equal' END AS Compare_1_3;
g1_WKT       g2_WKT       Compare_1_2  g3_WKT       Compare_1_3
POINT (5 5)  POINT (5 5)  Equal        POINT (5 6)  Not Equal

MS SQL STAsText function comments

En
STAsText Returns the Open Geospatial Consortium (OGC) Well-Known Text (WKT) representation of a geometry instance