I am attempting to write an sql stored procedure that will determine if a point is within a buffer. So far I have been able to hard code the values in the query and they work as expected but when I attempt to replace the hard coded values with variables then I get problems.
This works:
DECLARE #g geography;
Declare #Latitude float;
declare #Longitude float;
Set #g = geography::STPointFromText('POINT(' + CAST(#longitude as VARCHAR(16)) + ' ' + CAST(#latitude as VARCHAR(16)) + ')', 4326)
declare #bufloc geography = geography::Point(52.677777, -1.280786,
4326).STBuffer(1000)
SELECT CASE #g.STIntersects(#bufloc) WHEN 1 THEN '#g intersects #h'
ELSE '#g does not intersect #h'
END;
But if I declare a second set of coordinates and the try to pass variables into the #bufloc I break the query.
Declare #BufLongitude float; Declare #DistanceInMeteres int;
declare #bufloc geography = geography::STPointFromText('POINT(' +
CAST(#BufLatitude as VARCHAR(16)) + ' ' + CAST(#BufLongitude as
VARCHAR(16)) + ')', 4326).STBuffer(1000)
How would I write this to get things working? Ultimatly I would like to pass two coordinates into a stored procedure along with a distance parameter to use in the construction of the buffer and return true or false if the point can be located in the resulting buffer.
The query returns a false value it returns '#g does not intersect #h' when the hard coded query returns '#g intersects #h' for the same value.
Related
I have string coordinates in my table but I want to do some geographical functionalities, So I need first to convert this string value to geography.like this:
geography::STGeomFromText('POINT([location])', 4326).MakeValid().STDistance(#p)
but for sure this code didn't work as it needs here point not string coordinates.
The full code:
geography::STGeomFromText('POINT([location])', 4326).MakeValid().STDistance(#p);
DECLARE #p geography;
SET #p = geography::STGeomFromText('POINT({$Lon} {$Lat})', 4326);
Select TOP 1 id, location from branches where {$location} <= {$this->radius} order by {$location}
It's a little difficult to provide a perfect solution without seeing how the code is interporlating the variables, but SQL could be having issues recognizing your long/lat as strings with the STGeomFromText method.
Could you try something like this:
SELECT geography::STGeomFromText('POINT(' + CAST([$Long] AS VARCHAR(20)) + ' ' + CAST([$Lat] AS VARCHAR(20)) + ')', 4326)
Or more succinctly:
SELECT geography::Point([$Lat], [$Long], 4326)
I have a string:
DECLARE #UserComment AS VARCHAR(1000) = 'bjones marked inspection on system UP for site COL01545 as Refused to COD won''t pay upfront :Routeid: 12 :Inspectionid: 55274'
Is there a way for me to extract everything from the string after 'Inspectionid: ' leaving me just the InspectionID to save into a variable?
Your example doesn't quite work correctly. You defined your variable as varchar(100) but there are more characters in your string than that.
This should work based on your sample data.
DECLARE #UserComment AS VARCHAR(1000) = 'bjones marked inspection on system UP for site COL01545 as Refused to COD won''t pay upfront :Routeid: 12 :Inspectionid: 55274'
select right(#UserComment, case when charindex('Inspectionid: ', #UserComment, 0) > 0 then len(#UserComment) - charindex('Inspectionid: ', #UserComment, 0) - 13 else len(#UserComment) end)
I would do this as:
select stuff(#UserComment, 1, charindex(':Inspectionid: ', #UserComment) + 14, '')
This works even if the string is not found -- although it will return the whole string. To get an empty string in this case:
select stuff(#UserComment, 1, charindex(':Inspectionid: ', #UserComment + ':Inspectionid: ') + 14, '')
Firstly, let me say that your #UserComment variable is not long enough to contain the text you're putting into it. Increase the size of that first.
The SQL below will extract the value:
DECLARE #UserComment AS VARCHAR(1000); SET #UserComment = 'bjones marked inspection on system UP for site COL01545 as Refused to COD won''t pay upfront :Routeid: 12 :Inspectionid: 55274'
DECLARE #pos int
DECLARE #InspectionId int
DECLARE #IdToFind varchar(100)
SET #IdToFind = 'Inspectionid: '
SET #pos = CHARINDEX(#IdToFind, #UserComment)
IF #pos > 0
BEGIN
SET #InspectionId = CAST(SUBSTRING(#UserComment, #pos+LEN(#IdToFind)+1, (LEN(#UserComment) - #pos) + 1) AS INT)
PRINT #InspectionId
END
You could make the above code into a SQL function if necessary.
If the Inspection ID is always 5 digits then the last argument for the Substring function (length) can be 5, i.e.
SELECT SUBSTRING(#UserComment,PATINDEX('%Inspectionid:%',#UserComment)+14,5)
If the Inspection ID varies (but is always at the end - which your question slightly implies), then the last argument can be derived by subtracting the position of 'InspectionID:' from the overall length of the string. Like this:
SELECT SUBSTRING(#UserComment,PATINDEX('%Inspectionid:%',#UserComment)+14,LEN(#usercomment)-(PATINDEX('%Inspectionid:%',#UserComment)+13))
I have used this site before for help with various things in the past, and in this instance, I couldn't find anything in the search box, so apologies if this exists elsewhere.
In sql server 2005, I have several stored procedures that change various bits of code, and recently we have created a function that adds spaces into a defined string. So in theory, I pass a string into it, and I get a result as blocks of 4. When I run this manually, and define the actual text, it splits fine (I get #### 0000 012 returned) but when I execute the function within the SP, I get #### 0012 0012. Is there any reason why?
I have set a print command to the string before it gets passed into my function, and it prints "####0000012 " and the print after is "#### 0012 0012"
Below is the function code, with no declares:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER function [dbo].[udf_addspaces](#string varchar(255),#lengthbetween int)
returns varchar(100)
as
BEGIN
declare #i int, #stringlen float, #output varchar(255), #outputofloop varchar(4)
set #stringlen = LEN(#string)/#lengthbetween
set #output =''
set #i = 0
while #i <= #stringlen
BEGIN
set #outputofloop = left(#string,#lengthbetween)
if #lengthbetween < LEN(#string)
BEGIN
set #string = right(#string,LEN(#string)-#lengthbetween)
END
set #output = #output + #outputofloop +' '
set #i = #i+1
END
return #output
END
Here is the bit of the SP that executes this:
set #Consignment2 = (#Consignment) + rtrim(#Check14)
print #Consignment2
set #Consignment2 = dbo.udf_addspaces(#Consignment2,4)
print #Consignment2
Here are the lines it prints: (Note: #### replaces a 4 digit number, removed for security reasons)
####0000012
#### 0012 0012
Regards,
Luke M
Even though you've defined stringlen as a float, it will be an integer value, because the two values you're dividing are ints.
There's a difference between a char(14) mentioned in your comments, to a varchar(14). The char(14) is guaranteed to be 14 characters long. The varchar may not be.
I think the body of your function could be more succinctly expressed as this...
declare #result varchar(500)
select #result = ''
select
#result = #result
+ substring(#string, number*#lengthBetween+1, #lengthBetween)
+ ' '
from master..spt_values
where type='p'
and number <= (len(#string)/#lengthBetween)
return rtrim(#result)
Currently, I have a function to get list of columns of 1 table with detail attribute. And off course, there are some tables with a lot of columns. So, the output will be over 10.000 characters.
Here I test like this:
declare #aa nvarchar(max)
set #aa = dbo.fnGetColumnList('Table_Name')
print #aa
The result always has around 4000 characters. It looks like the SQL has truncated it.
What I know that when we declare nvarchar(max), SQL will supports up to 2^32-1 (2GB) for this string. But why it just has around 4000 characters?
When I execute like this:
select dbo.fnGetColumnList('Table_Name')
the result is correct.
And here is the code for the function:
-- get column list from table Mapping
ALTER FUNCTION [dbo].[fnGetColumnList] ( #tblName varchar (30))
RETURNS nvarchar(max)
AS
BEGIN
Declare #sql nvarchar(max)
set #sql = ''
SELECT #sql = #sql + case
when CHARINDEX('char', LOWER([DBType])) > 0 then ', ['+[DBColumn]+']' + ' ['+[DBType]+']' + ' ('+convert(varchar(10),[Length])+') NULL' + CHAR(13)
when CHARINDEX('char', LOWER([DBType])) > 0 then ', ['+[DBColumn]+']' + ' ['+[DBType]+']' + ' NULL' + CHAR(13)
ELSE ', ['+[DBColumn]+']' + ' ['+[DBType]+']' + ' NULL' + CHAR(13)
end FROM dbo.Mapping WHERE [DBTable] = #tblName
return #sql
END
Please advance.
This is almost always a variable assignment type problem, as explained in:
For Nvarchar(Max) I am only getting 4000 characters in TSQL?
If it's not that, then it's probably just the settings of Print to display too few characters:
nvarchar(max) still being truncated
Having looked at the updated code, it seems like it's the second issue, your print is truncating as it's not set to show enough characters.
You should see this by running
SELECT LEN(#aa)
You'll get a number larger than 4000, showing the value is held correctly in the variable.
As explained in Microsoft's nvar and nvarchar docs:
A common misconception is to think that with nchar(n) and nvarchar(n), the n defines the number of characters. However, in nchar(n) and nvarchar(n), the n defines the string length in byte-pairs (0-4,000). n never defines numbers of characters that can be stored. This is similar to the definition of char(n) and varchar(n).
There is an option in SQL Management Studio:
Tools > Options... > Query Results > SQL Server > Results to Text > Maximum number of characters displayed in each column
I have a table (locations) that has a field called Point (geometry). I wrote a query that passes the top and bottom latitude coordinates and the bottom and top longitude coordinates. I want to retrieve all records that are within the area of the coordinates I pass the stored procedure. When I run this it returns zero records even though I know there is a record that matches the criteria. Any ideas what I might be doing wrong?
DECLARE #categoryid AS int,#leftlong AS float,#rightlong AS float,#toplat AS float,#bottomlat AS float
DECLARE #searcharea geometry, #polygon AS varchar(500);
SET #leftlong = -85.605469
SET #toplat = 42.303468
SET #rightlong = -85.594912
SET #bottomlat = 42.297564
SET #polygon = CAST(#leftlong AS varchar(20)) + ' ' + CAST(#toplat AS varchar(20)) + ',' +
CAST(#leftlong AS varchar(20)) + ' ' + cast(#bottomlat AS varchar(20)) + ',' +
cast(#rightlong AS varchar(20)) + ' ' + cast(#bottomlat AS varchar(20)) + ',' +
cast(#rightlong AS varchar(20)) + ' ' + cast(#toplat AS varchar(20)) + ',' +
CAST(#leftlong AS varchar(20)) + ' ' + CAST(#toplat AS varchar(20))
SET #searcharea = geometry::STGeomFromText('POLYGON ((' + #polygon + '))', 0);
SELECT *
FROM locations l
WHERE l.point.STWithin(#searcharea) = 1
There are two likely potential sources of the problem:
Usage of geometry instead of geography type. When working with latitude and longitude data, you generally want to use the geography type in order to do calculations on the ellipsoid instead of on the plane. These calculations can different considerably - this is a lot of information available on this distinction in various articles such as this whitepaper.
Mismatching SRIDs - is the srid of the data in your locations table also 0 for all rows? If these do not match between your data and your #searcharea, no results will be returned.