Insert data to a spatial database in postgis - database

I have create a table which has 3 fields: id(integer), name(char) and surface(polygon). When i try to insert a new row in this table by executing:
INSERT INTO public."Area"
("ID", "Name", "Surface")
VALUES(0, 'myArea', POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)));
I get this error:
SQL Error [42601]: ERROR: syntax error at or near "0"
Position: 84
I searched in the documentation of postgis etc but i didnt find out how to define this field (same for points and linestring).
I also tried something like this:
INSERT INTO public."Area"
("ID", "Name", "Surface")
VALUES(1, 'myArea', ST_GeomFromText('POLYGON((8 4, 10.5 4, 10.5 1.5, 8 1.5, 8 4))'));
but the result was :
SQL Error [42804]: ERROR: column "Surface" is of type polygon but expression is of type geometry
Hint: You will need to rewrite or cast the expression.
Position: 76
Could you please help me to find out which is my mistake?
Thank you a lot for your time!

Try ST_PolygonFromText
instead of ST_GeomFromText.
Or declare the column as generic GEOMETRY, rather than POLYGON type.

The error message tells the column is of type polygon, which is a native postgres type. What one can do with this type is very limited and if you are working with spatial data, using Postgis and its geometry type is indicated.
To create a column containing geometries of the type polygon, with the projection 4326, you would do
CREATE TABLE test (my_poly geometry(polygon,4326));
You can then load data using ST_GeomFromText.
Since your column is of geometry type, there is an automatic cast from text to geometry, or you can force it. Unlike in your 1st query, note that the polygon definition must be enclosed between quotes.
insert into test values ('polygon((0 0, 0 1, 1 1, 1 0, 0 0))'::geometry)
At last, it is technically possible to create a Postgis geometry and to cast it to Postgres native polygon type (SELECT ST_GeomFromText('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')::polygon;), but doing so brings very little benefit since you still won't have access to most of Postgis functions (compute distances, reproject, compute intersections etc)

Related

PostGIS not recognizing geometry type after writing to database with geopandas

I have a PostGIS database set up that is spatially enabled.
engine = create_engine(f'postgresql://user:password#localhost:5432/{dbname}')
I have a valid geopandas dataframe (i.e., if I export as .shp or .gpkg I can load into a GIS app with no errors) with a geometry column named 'geometry'. I write these data to the database with:
gdf.to_postgis('table_name', con=engine, if_exists='append', index_label='id')
If I read all records from this table:
gpd.read_postgis('table_name', con=engine, geom_col='geometry')
I get the following warning:
SAWarning: Did not recognize type 'geometry' of column 'geometry' pandas_sql.meta.reflect(only=[sql])
If I try to execute an postgresql statement such as:
gpd.read_postgis('SELECT DISTINCT(st_cnty_fips) FROM table_name', con=self.engine, geom_col='geometry')
I get an error:
line 65, in _df_to_geodf
raise ValueError("Query missing geometry column '{}'".format(geom_col))
ValueError: Query missing geometry column 'geometry'
Using PGAdmin4 I can see that the column exists. What am I doing wrong?
Geopandas requires a geometry columna after filtering out geometry additionally or adding it should work.
The parameter geom_col='geometry' allows you to specify the name of this column that geopandas needs.
Need to add geometries.
For example:
SELECT your_query_with_out_geom, geometry FROM table_name;
In your case, could:
gpd.read_postgis('SELECT DISTINCT(st_cnty_fips), geometry FROM table_name', con=self.engine, geom_col='geometry')

Postgis query to update linestring

while executing this query i am getting error
UPDATE treedetailsentered
set geom_line=st_geomfromtext('LineString(('||longitude||' '||latitude||','||lon2||' '||lat2||'))', 4326);
error
ERROR: parse error - invalid geometry
HINT: "LineString((7" <-- parse error at position 13 within geometry
********** Error **********
this is how i created column in table for the linestring
ALTER TABLE public.treedetailsentered
ADD COLUMN geom_line geometry(LineString, 4326)
It's hard to tell what the exact problem is without knowing what type longitude, latitude have, but my guess is that you're not forming a proper string.
My advice is to debug this by first creating a proper text via a query that's simpler:
select 'LineString(('||longitude||' '||latitude||','||lon2||' '||lat2||'))'
Depending on what types you have, you might have to do some conversions, like this:
select 'LineString(('||longitude::text||' '||latitude::text||','||lon2::text||' '||lat2::text||'))'
If you already have texts, make sure that the numbers are properly formatted. Floats are expected to have a dot decimal separator for example.
I have added an extra bracket i removed that it worked for me.
UPDATE treedetailsentered set geom_line=ST_GeomFromText('LINESTRING(' || longitude || ' '||latitude||','||lon2||' '||lat2||')', 4326);

Get geometry from a varchar(max) in an update query

I've got a table full of WKT (well known text) in a varchar(max) column. This is formatted exactly as geometry. So, for example, one of the values is:
POLYGON ((174.893529167059 -37.0260462162965,174.89351593407 -37.0260221329151,174.893508034056 -37.0260077002766,174.893444415879 -37.0258916500588,174.893416916056 -37.0258414997842,174.893481733297 -37.0258186834198,174.893492016755 -37.0258150663863,174.89349653254 -37.025823316032,174.893512415978 -37.0258522827285,174.893556883897 -37.0259333832477,174.893591032956 -37.0259956661343,174.893604265986 -37.0260197504078,174.893575149738 -37.0260300006258,174.893529167059 -37.0260462162965))
However, I need to convert this varchar(max) field into a geometry field. Unfortunately, SQL Server needs to have some other information in order to do this, so I can't just change the type of the field from varchar(max) to geometry.
I've created a blank geometry column in the same table (MyGeometry) but I'm failing in trying to convert it. Here is my code (where 2193 is the CRS I'm dealing with). WKT is my varchar(max) field and MyGeometry is my new geometry field.
UPDATE MY_TABLE
SET MyGeometry = geometry::STPolyFromText('' + WKT + '', 2193)
EDIT - currently coming back saying the WKT is not valid (System.FormatException 24111 - the input isn't valid).
Which is strange as it matches up perfectly with some other inputs I have in how it's styled.
This will do :
UPDATE MY_TABLE
SET MyGeometry = geometry::STGeomFromText('POLYGON ((174.893529167059 -37.0260462162965,174.89351593407 -37.0260221329151,174.893508034056 -37.0260077002766,174.893444415879 -37.0258916500588,174.893416916056 -37.0258414997842,174.893481733297 -37.0258186834198,174.893492016755 -37.0258150663863,174.89349653254 -37.025823316032,174.893512415978 -37.0258522827285,174.893556883897 -37.0259333832477,174.893591032956 -37.0259956661343,174.893604265986 -37.0260197504078,174.893575149738 -37.0260300006258,174.893529167059 -37.0260462162965))', 0)
You can change that 'POLYGON....' to your VARCHAR(MAX) field.
0 at the end, which is SRID only relevant if you're using Geography.
You can also try :-
UPDATE MY_TABLE SET MyGeometry = GEOMETRY::STGeomFromText('POLYGON ((174.893529167059 -37.0260462162965,174.89351593407 -37.0260221329151,174.893508034056 -37.0260077002766,174.893444415879 -37.0258916500588,174.893416916056 -37.0258414997842,174.893481733297 -37.0258186834198,174.893492016755 -37.0258150663863,174.89349653254 -37.025823316032,174.893512415978 -37.0258522827285,174.893556883897 -37.0259333832477,174.893591032956 -37.0259956661343,174.893604265986 -37.0260197504078,174.893575149738 -37.0260300006258,174.893529167059 -37.0260462162965))',4326);
The value of SRID passed should be 4326 and not 0
You can check the URL below. I found this information in another similar question (older post) so pasting it without any changes
I found solution, SQL Server Spatial Tools
http://sqlspatialtools.codeplex.com/
Followings are the methods solved my problem.
IsValidGeographyFromText(string inputWKT, int srid)
Check if an input WKT can represent a valid geography. This function requires that the WTK coordinate values are longitude/latitude values, in that order and that a valid geography SRID value is supplied. This function will not throw an exception even in edge conditions (i.e. longitude/latitude coordinates are reversed to latitude/longitude).
SqlGeography MakeValidGeographyFromText(string inputWKT, int srid)
Convert an input WKT to a valid geography instance. This function requires that the WKT coordinate values are longitude/latitude values, in that order and that a valid geography SRID value is supplied.

Calling postgis ST_DWithin in a rails query

The following is being attempted in the console for a postgis enabled rails4.2 application.
#target = Target.last
#meter_radius = 1000
#valid_points = Target.where("ST_DWithin(#{#target.lat}, #{#target.lon}, #{#meter_radius}))
lat and lon are defined as decimal values. This translates into the following query
SELECT "targets".* FROM "targets" WHERE (ST_DWithin(38.656679, 15.984094, 1000))
with the error:
PG::UndefinedFunction: ERROR: function st_dwithin(numeric, numeric, integer) does not exist
I believe I need to declare the data type (geometric or geographic) for these values but am not sure how. I am also wondering whether the ST_DWithin function can work off of the 3857 data type, even though the documentation does not state so.
note the #target object also has a lonlat attributes defined as a spatial value in postgresql with :srid=>3857, :type=>"point" defined.
Update
#valid_points = Target.where("ST_DWithin(lonlat, ST_PointFromText('#{#target.lonlat}', #{#meter_radius}))
returns a result and thus appears syntactically valid.
SELECT "targets".* FROM "targets" WHERE (ST_DWithin(lonlat, ST_PointFromText('POINT (15.984094 38.656679)', 3857), 1000))
However the result is incorrect. It essentially finds all the points of the table. Being of SRID type, this needed to be expressed in degrees, not meters.
One answer, leveraging the lonlat spatial point stored:
#target = Target.last
#degree_radius = 0.2249
#valid_points = Target.where("ST_DWithin(lonlat, ST_PointFromText('#{#target.lonlat}', #{#degree_radius}))
which returns a result and thus appears syntactically valid.
SELECT "targets".* FROM "targets" WHERE (ST_DWithin(lonlat, ST_PointFromText('POINT (15.984094 38.656679)', 3857), 0.2249))

How I can contract the polygon geometry that approximates and is covered by a specified circle in SQL Server?

How I can contract the polygon geometry that approximates and is covered by a specified circle in SQL Server?
I have a circle
DECLARE #circle geography;
SET #circle = geography::STGeomFromText('CURVEPOLYGON(CIRCULARSTRING(2 4, 4 2, 6 4, 4 6, 2 4))',4326);
How I can get POLYGON that is covered by this circle?
NOTE: Requires SQL 2012 or higher.
Now I understand completely what you are looking for, you'll find the STCurveToLine() method useful.
For instance:
DECLARE #circle GEOGRAPHY;
SET #circle = GEOGRAPHY::STGeomFromText('CURVEPOLYGON(CIRCULARSTRING(2 4, 4 2, 6 4, 4 6, 2 4))',4326);
SELECT #circle.STCurveToLine().STAsText();
This will return a POLYGON instance. Depending on the required accuracy and how complex you want the object to be, you may require the Reduce() function to reduce the number of points.
SELECT #circle.STCurveToLine().Reduce(1000); -- Or whatever number is appropriate;

Resources