It should accept only this format: (232.343244)
I think this specification is confusing the issue. It isn't really a format that shows variation. I believe you meant something like either ###.######
or even XXX.YYYYYY
. If you are accepting Latitude and Longitude values, then those have valid ranges, and valid values can have single or double digits to the left of the decimal, just as you show in the "Data that can be entered by user:" examples. And, they can be positive or negative, so you need to allow for an optional preceding minus sign (-), so maybe either [-]###.######
or [-]XXX.YYYYYY
. So to describe this we would say: "up to 3 digits to the left of the decimal, and up to 6 digits to the right of the decimal."
Also, there is not much benefit to validating the number of digits to the right of the decimal since that is merely an issue of precision and can be rounded up or truncated. Please see this answer for details: What is the maximum length of latitude and longitude?
The following code validates the actual valid ranges for both types of values (since they have different ranges -- why allow 3 digits to the left of the decimal for Latitude when it won't ever use more than 2 digits?).
Also, I was not sure what to make of your AND CAST(A.GPS_LONGITUDE AS NVARCHAR) NOT LIKE'%*%')
condition, but I duplicated it here. It can be changed easily enough if the intention was to skip values that consist of only one or more asterisks. Lastly, if there was a specific purpose in casting the NVARCHAR
field to an NVARCHAR
then it should be stated in the Question (and if so, you should specify a max length, as in NVARCHAR(30)
rather than just NVARCHAR
).
SET NOCOUNT ON;
DECLARE @TestValues TABLE (GPS_LATITUDE NVARCHAR(50), GPS_LONGITUDE NVARCHAR(50));
INSERT INTO @TestValues (GPS_LATITUDE, GPS_LONGITUDE) VALUES
(N'20.0', N'20.212'),
(N'-20.0', N'-20.212'),
(N'91.0', N'20.212'),
(N'-91.0', N'20.212'),
(N'41.0-', N'200.212'),
(N'-41.0', N'200.212'),
(N'-2*0.0', N'-20.212'),
(N'-20.0', N'-2*0.212'),
(N'2-0.0', N'2-0.212'),
(N'20.123456789', N'20.987654321'),
(N'90.000001', N'180.000001'),
(N'12.345.678', N'87.654.321'),
(NULL, NULL),
(N'', N''),
(N'34.2a5', N'45.6b923');
SELECT tmp.GPS_LATITUDE,
tmp.GPS_LONGITUDE,
CASE
WHEN tmp.GPS_LATITUDE LIKE N'%[^.0-9*-]%' OR LEN(tmp.GPS_LATITUDE) > 11
THEN 'Invalid Latitude (bad character OR too long). '
WHEN tmp.GPS_LATITUDE NOT LIKE N'%*%' AND ISNUMERIC(tmp.GPS_LATITUDE) = 0
AND LEN(tmp.GPS_LATITUDE) > 0
THEN 'Invalid Latitude (not a number). '
WHEN ISNUMERIC(tmp.GPS_LATITUDE) = 1
AND CONVERT(FLOAT, tmp.GPS_LATITUDE) NOT BETWEEN -90.0 AND 90.0
THEN 'Invalid Latitude (range outside of -90.0 to 90.0). '
ELSE ''
END +
CASE
WHEN tmp.GPS_LONGITUDE LIKE N'%[^.0-9*-]%' OR LEN(tmp.GPS_LONGITUDE) > 11
THEN 'Invalid Longitude (bad character OR too long). '
WHEN tmp.GPS_LONGITUDE NOT LIKE N'%*%' AND ISNUMERIC(tmp.GPS_LONGITUDE) = 0
AND LEN(tmp.GPS_LONGITUDE) > 0
THEN 'Invalid Longitude (not a number). '
WHEN ISNUMERIC(tmp.GPS_LONGITUDE) = 1
AND CONVERT(FLOAT, tmp.GPS_LONGITUDE) NOT BETWEEN -180.0 AND 180.0
THEN 'Invalid Longitude (range outside of -180.0 to 180.0). '
ELSE ''
END AS [Validation]
FROM @TestValues tmp;
Returns:
LATITUDE LONGITUDE Validation
-------- --------- ----------
20.0 20.212
-20.0 -20.212
91.0 20.212 Invalid Latitude (range outside of -90.0 to 90.0).
-91.0 20.212 Invalid Latitude (range outside of -90.0 to 90.0).
41.0- 200.212 Invalid Latitude (not a number). Invalid Longitude (range outside of -180.0 to 180.0).
-41.0 200.212 Invalid Longitude (range outside of -180.0 to 180.0).
-2*0.0 -20.212
-20.0 -2*0.212
2-0.0 2-0.212 Invalid Latitude (not a number). Invalid Longitude (not a number).
20.123456789 20.987654321 Invalid Latitude (bad character OR too long). Invalid Longitude (bad character OR too long).
90.000001 180.000001 Invalid Latitude (range outside of -90.0 to 90.0). Invalid Longitude (range outside of -180.0 to 180.0).
12.345.678 87.654.321 Invalid Latitude (not a number). Invalid Longitude (not a number).
NULL NULL
34.2a5 45.6b923 Invalid Latitude (bad character OR too long). Invalid Longitude (bad character OR too long).
In the application UI, there will be an upload button. Pressing the upload button sends the data to the database and it validates in a stored procedure.
Since you have the opportunity to trap the data before it hits the database, you really would be better off doing this validation in the app code as it is much easier (and more efficient) to do that.