Check if unique value exists before updating in MSSQL - sql

I have a table containing a list of MAC addresses that in some cases has been padded to twelve digits and in other cases has not.
ie: 00FF12345678 OR FF12345678
There are cases where both values exist in this table. I have a function that pads the value with the two zeroes and I can count the occurrence of these duplicates, but I don't have the time or patience to manually remove the duplicates or pad those that do not already have a record.
I figured I could update the 10 digit values to their correct value with the following statement:
UPDATE [rs_DEVICES]
SET [device] = dbo.pad_zero(12,[device])
WHERE LEN([device]) < 12
Of course this doesn't work because I need to only update those values that do not have an existing 12 digit record. The unique constraint on this column stops me from doing this.
I need some sort of IF EXISTS statement in the WHERE clause but I haven't been able to come up with anything that works.
Using MSSQL Server 2008 R2.
Thoughts?

This does the job for you:
UPDATE [rs_DEVICES]
SET [device] = dbo.pad_zero(12,[device])
WHERE LEN([device]) < 12 AND NOT EXISTS (
SELECT 1 FROM rs_DEVICES r1 WHERE r1.device = dbo.pad_zero(12,[device])
)
I think it's self explanatory, but if you have any questions please comment.
Honestly though, I recommend you to fix the real problem. Reassign the current references to the length=10 records to their respective length=12 siblings and then remove them.

Related

Violation of PRIMARY KEY constraint PK. Cannot insert duplicate key in object (table1), The duplicate key value is (Col1, Col2, Col3, Col4)

I have a product entry page through we keep on adding product entries in our database.
Product location wise there are 2 series. e.g., ABCTMP(Series(1-max)) and XYZ(Series(1-max)).
Table is having primary key constraint which is a combination of 4 columns. Out of 4, only one is giving an issue while increment series combination wise.
That first column is location wise product code as stated above and it is of data type char(20) as it stores values like ABCTMP01 and through classic asp code. We increment that last 01 value by addition of one into existing value.
Right now, facing issue when last value reaches 99 and turns to 100. It generates code 100 through code but unable to insert in database and giving this error that was due to existing entry in database.
Duplicate key part is same one which I mentioned above in subject/header. If I delete record from table of record no. 100 to check, it gives me proper record of 99 through above query and through above classic asp code, it generates next code as 99+1 = 100.
But when I again try to add next series record for 101, even through SQL mgt studio, it gives me below error.
Violation of PRIMARY KEY constraint 'PK'. Cannot insert duplicate key in object 'prdct_mst_tab'. The duplicate key value is (PWATERTMP100 , 006, Y, 01). The statement has been terminated.
Have tried by dropping constraint and changing size of data type char(20) to char(30) as there are dependencies on table. But not worked. Then, have tried by changing data type from char(30) to varchar(30), still not worked. Then again tried by manually
executing insert command
in SQL itself, but same error occurred for 101th record.
Before generating next series, there is select statement to check latest inserted record which will get incremented later.
For generating next record of 101,there select statement must show last inserted record of 100, but it's still giving 99th record and code is generating as 100 again and the error continues the same. I do not understand why it's not taking 100th record when I execute SELECt statement in SQL mgt studio. DataType of that PWATERTMP100 column is char(20).
Below my classic asp code for series generation and SQL 'SELECT top 1 *' statement for record count for location wise product.
select top 1 *
from prdct_mst_tab
where pmt_prdct_cd like 'PWATER%'
and pmt_umt_unit_cd='006'
AND PMT_CMT_CMPNY_CD='01'
order by pmt_prdct_cd desc
Classic ASP Code: -
If recordset.eof Then
getcode="ABCTMP01"
Else
getcode = clng(Mid(recordset("Column1"),10,20))
response.write("Hello" & getcode)
getcode = getcode +1
response.write("<br />Hello" & getcode)
getcode = "ABCTMP" & getcode
response.write("<br />Hello" & getcode)
End if
Below for adding generated product code in database table.
Sql is as below
select * from Table1
recordset.open sql,con,3,2
recordset.addnew
recordset("Column1")=getcode
recordset.update
recordset.close
Note : Values given above are sample one.
I want the record gets inserted even when it turns from 99 to 100, means code will become ABCTMP99 - ABCTMP100 and continue from series starting with 100 range(3 digits)like 100, 101, 102....
The problem is that the order by in this:
select top 1 * from prdct_mst_tab
where pmt_prdct_cd like 'PWATER%'
and pmt_umt_unit_cd='006'
AND PMT_CMT_CMPNY_CD='01'
order by pmt_prdct_cd desc
Does not do what you expect.
Try running this in management studio:
select * from prdct_mst_tab
where pmt_prdct_cd like 'PWATER%'
and pmt_umt_unit_cd='006'
AND PMT_CMT_CMPNY_CD='01'
order by pmt_prdct_cd desc
You'll see that the 100 appears before 99 because it is ordering it alphanumerically not numerically.
In fact you will also see that 10 appears before 9 - how did you ever get past this?
You have a fundamental design flaw. I will add to that by posing a solution which cements the design flaw in place and introduces new bugs. But it will give you a result.
One workaround is to do something this:
select
MAX(
CASE
WHEN ISNUMERIC(RIGHT(RTRIM(pmt_prdct_cd),3)) = 1
THEN RIGHT(RTRIM(pmt_prdct_cd),3)
ELSE '0' + RIGHT(RTRIM(pmt_prdct_cd),2)
END
) As LargestNumber
from prdct_mst_tab
where pmt_prdct_cd like 'PWATER%'
and pmt_umt_unit_cd='006'
AND PMT_CMT_CMPNY_CD='01'
What does this do?
It checks if the last three characters are a number. If it is it uses it.
If it isn't a number it grabs the last two characters and puts a zero in front.
Then it picks the largest number out of all of those.
note - this returns a number, it doesn't return the full product code. So you'll need to remove the ASP Mid code that tries to pull the number out.
This might work until you find some other data or case that you haven't mentioned yet. Like for example if there are trailing characters that aren't numeric. Or for when you need a four character number
Make no mistake - you have a fundamental design flaw and this just prolongs the issue, adds complexity, and introduces more bugs down the track
Some basic observations:
char is a bad data type for this
It has concurrency issues - if two requests call this at the same time (easily done from a web app), it returns the same number and they both try and insert a duplicate value
You should not be assigning and storing incrementing numbers like this. Just use an IDENTITY in the database.
I guess since you are using classic ASP, you are not in a situation that you can redesign this.
You need to decide whether you are going to patch this with something that will introduce new bugs or fix it properly.
Does each product code really need to be incremented within it's own domain like that? Is there any issue with having ABC01 then DEF02 then XYZ03?

0 rows updated while using update query in oracle

When I am trying to update a column with character datatype using update statement. It says 0 rows update and does not throw any error. As the number of columns are much i tried using where clause using specific column out of it...where it updates the row.
Issue is when all the columns are used to alter the value, it gives back 0 rows updated. I have to automate it in vba code/tool so that it could update using all the rows. I identified the columns using which the value is not being updated but there is no error return.
It only says:
0 rows updated.
But what is wrong with that specific column(datatype...decimal).
Please help. I have searched whole internet but no results.
If you are trying to update a specific value in your database and only that one, you may have a rounding issue. This mean the value you see is not the exact value stored.
So you may try to update it with a specific range.
First select what you want to update:
select rowid from table_1
where val_x between <x>-<upsilon> and <x>+<upsilon>;
Update if you have only one value;
update table_1 set val_x = <new_val>
where val_x between <x>-0.001 and <x>+0.001
;
(otherwise, if more than 1 value, decrease <upsilon> to 0.0001, etc.)
Hope it helps

MS SQL Server Zero Padding

EDIT:
I'm changing column datatype to Varchar, should suggestion work, answer will be upvoted
Full Story:
I receive data for a person with an associated temporary number for every person that is 5 digits long, I process this information and then send variables to a stored procedure that handles the inserting of this data. When sending the variables to the stored procedure I appear to be losing any prefixed 0's.
For example:
Number sent to stored Proc - Number actually inserted column
12345 - 12345
01234 - 1234
12340 - 12340
This only appears to be happening for numbers with a 0 in front. Meaning if I received:
00012 it would insert as 12
Is there a way where I could either update the column to always 0 pad to the left by a fixed number, meaning if we got 12 it would automatically make the value 00012.
OR
Is there a way to do this with the variable when its received by the stored procedure before the variable is inserted into the table.
Something along the lines of:
SET #zeroPaddedFixedNum = LeftPad(#numberRecieved, '0', 5);
Additionally, I now need to stop any more numbers from inserting and update all current incorrectly lengthed numbers. Any suggestions?
Perhaps it's just my Google ability that has failed but I have tried searching numerous pages.
For this, the column should be of varchar datatype. You can then do this
Insert into table(col)
select right('00000'+cast(#var as varchar(5)),5)
EDIT : To update existing data
Update table
set col=right('00000'+cast(col as varchar(5)),5)
where len(col)<5
As pointed out, you'll have to use VARCHAR(5) for your needs... But I would not change the columns type, if the values stored are numbers actually. Rather use one of the following, whenever you pass these values to your SP (You might use a computed column or a VIEW though).
Try
SELECT REPLACE(STR(YourNumber,5),' ','0');
The big advantage: In cases, where your number exceeds 5 digits, this would return *****. It is better to get an error than to get wrong numbers... Other approaches with RIGHT() might truncate your result unpredictably.
With SQL Server 2012 you should use FORMAT()
SELECT FORMAT(YourNumber,'00000')

Access 2010 SQL - UPDATE query not working

I need to create a query for updating a column in a table with values taken from another table and matching a field.
These are the 2 tables:
tblMain
ID Autonumbering
Key Text
Stat1 Integer
tblStat1
ID Autonumbering
Key Text
Freq Integer
I want to UPDATE the tblMain.Stat1 column with tblStat1.Freq value on each record in which tblMain.Key = tblStat1.Key.
I tried this syntax (found somewhere as an example)
UPDATE tblMain
SET tblMain.Stat1 = tblStat1.Freq
WHERE tblMain.Key = tblStat1.Key;
This doesn't work and returns an error on the 2nd row.
After some trials I found that the correct syntax (built with the Access query generator) is this:
UPDATE (tblMaibn INNER JOIN tblStat1 ON tblMain.Key = tblStat1.Key)
SET tblMain.Stat1 = tblStat1.Freq;
In this 2nd syntax, there is no trace of the WHERE condition.
Can someone help me to understand what's wrong with the 1st syntax.
Since I'm building a new table (the join), how can it work on tblMain?
As I said, I found the wrong syntax as an example of UPDATE statement.
Thank you in advance.
Bye,
Ivano
What is happening in your first query on the 2nd row, is that Access isn't aware of what tblStat1 represents in your query.
The reason your 2nd query is working is because it uses an inner join on the relevant key. In order for SQL to be aware of what record in tblMain relates to which record in tblStat1, you need to use a join.
You can see in the generated code that it is updating your desired table, but joining onto the second table. The where condition is redundant as you're updating every record.
In 1st syntax, you can change:
UPDATE tblMain
SET tblMain.Stat1 = (SELECT Freq
FROM tblStat1
WHERE tblMain.Key = tblStat1.Key)

How to delete a common word from large number of datas in a Postgres table

I have a table in Postgres. In that table more than 1000 names are there. Most of the names are start with SHRI or SMT. I want to delete this SHRT and SMT from the names and to save original name only. How can I do that with out any database function?
I'll step you through the logic:
Select left(name,3) from table
This select statement will bring back the first 3 chars of a column (the 'left' three). If we are looking for SMT in the first three chars, we can move it to the where statement
select * from table where left(name,3) = 'SMT'
Now from here you have a few choices that can be used. I'm going to keep to the left/right style, though replace could likely be used. We want the chars to the right of the SMT, but we don't know how long each string is to pick out those chars. So we use length() to determine that.
select right(name,length(name)-3) from table where left(name,3) = 'SMT'
I hope my syntax is right there, I'm lacking a postgres environment to test it. The logic is 'all the chars on the right of the string except the last 3 (the minus 3 excludes the 3 chars on the left. change this to 4 if you want all but the last 4 on the left)
You can then change this to an update statement (set name = right(name,length(name)-3) ) to update the table, or you can just use the select statement when you need the name without the SMT, but leave the SMT in the actual data.