geometry STContains and STIntersects can differ for a point on a polygon boundary. I include that boundary case before deciding which predicate matches an application meaning of inside.

A familiar word can hide a boundary rule
A user can say a point is inside a region while intending its edge to count too. Another rule can require a point strictly in the interior. Those meanings need an explicit predicate contract. A method name alone doesn’t settle the application wording.
STContains and STIntersects both return a bit for two geometry instances. They ask different spatial questions. This example compares both against one square. Its result specification keeps the boundary outcomes separate from the interior case.
I’d discuss the edge rule before writing a filter that assigns points to regions. Shared boundaries can also make assignments overlap when inclusion is permitted on each side. This four-point demonstration doesn’t implement a unique-region assignment policy. It only exposes the predicate distinction.
Compare interior, edge, corner and exterior
The polygon is a two-by-two square beginning at the origin. Its test points lie at the center, on the left edge, at the origin corner and outside to the right. All instances use spatial reference identifier zero.
The interior point is expected to produce true for both relationships. The edge and corner produce false for STContains but true for STIntersects. The exterior point produces false for both. Each case label remains beside the selected coordinates and results.

X and Y are displayed as decimal(12,3). The relationship columns retain their native bit type. Those explicit types keep the output contract small and complete. A missing coordinate isn’t introduced as a substitute for an exterior point.
WITH PolygonInput AS
(
SELECT geometry::STGeomFromText(
N'POLYGON((0 0, 2 0, 2 2, 0 2, 0 0))', 0) AS Region
), Points AS
(
SELECT Id, CAST(CaseLabel AS varchar(20)) AS CaseLabel,
geometry::STGeomFromText(PointText, 0) AS TestPoint
FROM (VALUES (1, 'Interior', N'POINT(1 1)'), (2, 'Edge', N'POINT(0 1)'),
(3, 'Corner', N'POINT(0 0)'), (4, 'Exterior', N'POINT(3 1)'))
AS v(Id, CaseLabel, PointText)
)
SELECT p.Id, p.CaseLabel, CAST(p.TestPoint.STX AS decimal(12,3)) AS X,
CAST(p.TestPoint.STY AS decimal(12,3)) AS Y,
g.Region.STContains(p.TestPoint) AS ContainsPoint,
g.Region.STIntersects(p.TestPoint) AS IntersectsPoint
FROM PolygonInput AS g
CROSS JOIN Points AS p
ORDER BY p.Id;
Choose the predicate from the intended rule
If this point-in-polygon contract includes the edge, STIntersects demonstrates that inclusion for these selected points. If it excludes the edge, the containment result demonstrates the other choice. Broader geometry-to-geometry questions need their own examples. Don’t generalize a point case into every shape relationship.
I can justify excluding boundary points from an interior measurement. A coverage or contact check can require them instead. State that choice in plain language beside the query. Otherwise a correct spatial result can still disappoint the consumer.
The source coordinates are exact small integers rather than noisy measurements. Real-world coordinate uncertainty can introduce another boundary policy. This script doesn’t invent a tolerance or move points across the edge. It compares the supplied locations as written.
Keep reference identity and proof scope visible
Two geometry instances with different spatial reference identifiers give NULL from these methods. This example keeps every identifier equal. It doesn’t change labels to pretend a coordinate transformation occurred. An actual transformation is another operation requiring a suitable contract.
The complete script reads a literal polygon and point list through CTEs. It creates no objects or session settings. ORDER BY fixes the four-case sequence. The original polygon text remains available in the copyable SQL.
Compare every full coordinate and bit tuple with its SQL types. Include both boundary cases as well as interior and exterior. Keep the containment and intersection flags beside each other. A successful center point alone wouldn’t establish the selected inclusion rule.
Say what inside means for your data, then pick the predicate.
Inside is not a complete boundary policy, it is wording that needs a precise spatial relationship.
Published by Pinal Dave on SQLAuthority. More of my work at pinaldave.com.
Discover more from SQL Authority with Pinal Dave
Subscribe to get the latest posts sent to your email.




