I realize there are similar questions here but none of them are exactly what I need. I have a SQL sproc that part of it executes a view. I have 3 databases that are identical in design and function but the data is different and I am getting this error on only one of them. If i take the view from the erroring DB and execute it on one of the others, it runs just fine. The weirdest part is that this view worked, then stopped, then fixed itself and started working again and when I started making changes to some data, it stopped again.
I have boiled it down to this specific line;
Left(AO.Name,PATINDEX('%-%',AO.Name)-1) as ColumnName
The interesting part is if i change '%-% to be '%' the error goes away and my SPROC executes properly.
I have five questions;
Why am i getting this error when I have the '%-%' but not '%'? Whats the difference and what kind of a change is made by using one vs the other?
What does this error mean?
Why would the exact same view work properly on two other identical databases but not this one?
Why would this stop working after it was working, then somehow fix itself and then break itself again after some data manipulation?
Is there a better method outside of PATINDEX that I could use?
Any help is appreciated. Thank you.
This is going to happen when there is no hyphen in the string.
First, you can replace PATINDEX() with CHARINDEX() in this case:
LEFT(AO.Name, CHARINDEX('-', AO.Name) - 1) as ColumnName
That doesn't fix the problem, but it is simpler to follow.
Then, the problem is that AO.Name has no hyphen. In that case PATINDEX() (and CHARINDEX() too) returns 0. You subtract 1 and the value is illegal as a second argument to LEFT().
The easiest solution is to put a hyphen at the end:
LEFT(AO.Name, CHARINDEX('-', AO.Name + '-') - 1) as ColumnName
Related
I have tried looking for answers online, but I am lacking the right nomenclature to find any answers matching my question.
The DB I am working with is an inconsistent mess. I am currently trying to import a number of maintenance codes which I have to link to a pre-existing Excel table. For this reason, the maintenance code I import have to be very universal.
The table is designed to work with 2-3 digit number (time lengths), followed by a time unit.
For example, SERV-01W and SERV-03M .
As these used to be added to the DB by hand, a large number of older maintenance codes are actually written with 1 digit numbers.
For example, SERV-1W and SERV-3M.
I would like to replace the old codes by the new codes. In other words, I want to add a leading 0 if only one digit is used in the code.
REPLACE(T.Code,'-[0-9][DWM]','-0[0-9][DWM]') unfortunately does not work, most likely because I am using wildcards in the result string.
What would be a good way of handling this issue?
Thank you in advance.
Assuming I understand your requirement this should get you what you are after:
WITH VTE AS(
SELECT *
FROM (VALUES('SERV-03M'),
('SERV-01W'),
('SERV-1Q'),
('SERV-4X')) V(Example))
SELECT Example,
ISNULL(STUFF(Example, NULLIF(PATINDEX('%-[0-9][A-z]%',Example),0)+1,0,'0'),Example) AS NewExample
FROM VTE;
Instead of trying to replace the pattern, I used PATINDEX to find the pattern and then inject the extra '0' character. If the pattern wasn't found, so 0 was returned by PATINDEX, I forced the expression to return NULL and then wrapped the entire thing with a further ISNULL, so that the original value was returned.
I find a simple CASE expression to be a simple way to express the logic:
SELECT (CASE WHEN code LIKE '%-[0-9][0-9]%'
THEN code
ELSE REPLACE(code, '-', '-0')
END)
That is, if the code has two digits, then do nothing. Otherwise, add a zero. The code should be quite clear on what it is doing.
This is not generalizable (it doesn't add two zeros for instance), but it does do exactly what you are asking for.
So this is my third question in so many hours. Thanks again to everyone who has taken the time to help me through my SQL ordeal. I think this might be my last tango for the night, so here goes:
After taking some very good advice from #Vojtěch Dohnal, I converted one of my queries from a concatenated string to a parameterized SQL query here:
PARAMETERS NewPrefix TEXT; SELECT MAX([Suffix]) FROM [SalesTable] WHERE [Prefix] = [NewPrefix];
From what I can tell, this should be the right syntax for creating a parameterized query; the user will define what should go into the NewPrefix field and it will find the appropriate max function based on that. However, whenever I go to execute this query it hits me with the same 'Run-time error '5'; Invalid procedure call' error I've been wrestling with for about 9 hours now haha
I went ahead and tried to test the same query in the Access SQL query window, and I receive an error message there claiming: "This expression is typed incorrectly, or it is too complex to be evaluated. For example, a numeric expression may contain too many complicated elements. Try simplifying the expression by assigning parts of the expression to variables".
I'm not sure how to get around this. I don't think the syntax is wrong, but I can't find anything to compare it to on the Internet. I've used the debugger to step through and it looks like all of the values and variables and fields are populated correctly, but when it gets to the execute command it crashes with the same singularly unhelpful error message.
Thanks again for anyone who can help.
So it looks like the main problem that I was running into was that the "Prefix" field was actually a calculated field in my underlying Access table. For whatever reason, Access doesn't want to work with calculated fields with SQL; when I took out the calculation and just made the Prefix column a regular field, everything seems to work perfectly. I'm not really happy with this but it seems to work and that's what matters. Thanks to everyone who took the time to try and help me with this stuff. Cheers!
Edit: the solution provided by vax was successful, and should work for just about anyone facing a similar issue, as it replaces 4 different types of spacing, not just spaces. Thanks to all who provided help!
I have a table that gives industry names, but for one of the columns the distinct values have duplicates.
Here is the query I have:
select distinct replace(final_industry,' ','') from industryNorm
this is the results that are generated:
Automotive,AerospaceandDefense,Transportation,Travel,IndustrialProducts,andInfrastructure
Automotive,AerospaceandDefense,Transportation,Travel,IndustrialProducts,andInfrastructure
Communications,Media&Technology
ConsumerIndustriesandRetail
ConsumerIndustriesandRetail
Energy,Healthcare&ProcessIndustries
FinancialServices
FinancialServices
As you can see, many of the repeat. It seems that they still have spaces at the end, but I don't understand why, as I've run a replace function to get rid of them. I also ran a replace to put a | in the place of any space and when I do that the spaces at the end don't show up. Why is that? What can I do?
Can anyone help me out with this? Thanks!
Try RTrim() and LTrim() instead of Replace(). Trim() will take care of other characters than just ' '.
If you believe the problem is due to other white spaces I had a similar question that someone answered
select distinct replace(replace(replace(replace(
final_industry
,char(9)/*tab*/,'')
,char(10)/*newline*/,'')
,char(13)/*carriage return*/,'')
,char(32)/*space*/,'')
from industryNorm
You might be running into a very, very old bug in the replace function.
This is going to seem dumb, and that's because it is, but try putting multiple replaces in:
replace(replace(final_industry,' ',''), ' ','')
It might not help in your case but I've had times where the first replace didn't actually replace everything properly.
Here is some more explanation of why/how this happens: https://www.xaprb.com/blog/2005/11/15/a-bug-in-microsoft-sql-servers-replace-function/
Solution given by user Vax.
select distinct replace(replace(replace(replace(
final_industry
,char(9)/*tab*/,'')
,char(10)/*newline*/,'')
,char(13)/*carriage return*/,'')
,char(32)/*space*/,'')
from industryNorm
I have to write a select statement following the following pattern:
[A-Z][0-9][0-9][0-9][0-9][A-Z][0-9][0-9][0-9][0-9][0-9]
The only thing I'm sure of is that the first A-Z WILL be there. All the rest is optional and the optional part is the problem. I don't really know how I could do that.
Some example data:
B/0765/E 3
B/0765/E3
B/0764/A /02
B/0749/K
B/0768/
B/0784//02
B/0807/
My guess is that I best remove al the white spaces and the / in the data and then execute the select statement. But I'm having some problems writing the like pattern actually.. Anyone that could help me out?
The underlying reason for this is that I'm migrating a database. In the old database the values are just in 1 field but in the new one they are splitted into several fields but I first have to write a "control script" to know what records in the old database are not correct.
Even the following isn't working:
where someColumn LIKE '[a-zA-Z]%';
You can use Regular Expression via xQuery to define this pattern. There are many question in StackOverFlow that talk about patterns in DB2, and they have been solved with Regular Expressions.
DB2: find field value where first character is a lower case letter
Emulate REGEXP like behaviour in SQL
We have recently had to do some work with an OpenEdge database that a third party product uses, and today (after much hair-pulling), we finally identified why a view was returning no results.
This view in question combines about 100 separate tables, and is then queried against (we have limited rights to this database). One of the fields returned by this view is a hard-coded string literal, along the lines of
'John Smith' AS TheName
We were having difficulty running queries that included this string, which we were trying to RTrim (the view returned a lot of trailing spaces) and then concatenate with another field.
However, if we used RTrim on this field then, instead of returning an error message, or a null or something like that, the row simply wasn't returned. We weren't trying to use it in a WHERE clause or JOIN, this was simply part of the SELECT ... FROM VIEWNAME. After reviewing the view, it seemed that the view had erroneously detected the length of the string as 9 characters (no length was specified in the definition), and RTrim just didn't work.
Now, I could understand why this might lead to an error message, or a NULL value in the SELECT, but why would the row simply not be returned at all? This doesn't seem like good SQL behaviour and I've never seen it happen with any other RDBMS.
Other info : we're test querying via ODBC and WinSQL, with a view to this being included in an existing ASP.NET app. We don't have access to the backend except via this, although we do have rights to create views.
Update : As a freaky follow-up, we have now discovered that if we attempt to query this view without any WHERE clause, no records are returned. This may have the same cause.
This sounds like it could be related to the SQL-WIDTH within the progress database. One problem with Progress is that if the content of the field exceeds the SQL-WIDTH then you will get strange SQL behaviour (sometimes the driver might fail, other times you get no results).
To identify this you need to use the dbtool command to check for SQL-WIDTH's that may be exceeded.
Make sure you don't have blanks. Trimming doesn't remove blanks only spaces. Blanks are also not nulls. There is a difference in the character set while it is not visibly different in your editor.
I have run into this with a few databases, DBII, Oracle, PostGreSQL. Check the character set of your editor and try viewing the tables, you might see nothing or you might see big rectangles.
That sounds like very strange behavior. Just code around it, do the trim and/or string manipulation in the application and go on your way.