Basically, I am looking to modify a stored procedure that I have in my database already that updates a table's records (table x) with data coming from a web application. After updating table x, I want to develop that stored procedure to check table x to see if there exist anymore records for that instance of the primary key where column_z is null. Basically, something like
ALTER PROCEDURE [cred].[UpdateTablex]
(#field0 int,
#field1 int,
#field2 int,
#field3, int,
#field4 VARCHAR(100),
#field5 datetime,
#field6 datetime)
AS
UPDATE tablex
SET field4 = #field4,
field6 = #field6
WHERE field1 = #field1 AND
field2 = #field2 AND
field3 = #field3 AND
field0 = #field0 AND
field5 = #field5;
The rest of this will be psuedocode for my idea and the way I thought it might be developed
IF ((SELECT COUNT(field0) FROM tablex WHERE field6 is null AND field2 = #field2
AND field3 = #field3 AND field5 = #field5) equals 0)
exec cred.Demobilize(#field0, #field1);
Or simply, if that Select statement returns any results indicating that field6 is null anywhere then we do nothing. Obviously that would mean then that if the Select statement returns nothing, then I want to execute another stored procedure.
This is probably something simple so please forgive me as I'm kinda new to certain types of SQL syntax and usage, this being one of them.
Also, could anybody point me in a proper direction to further educate myself on topics like this?
Thank you.
You can do the if without using a variable:
IF (0 = (SELECT COUNT(field0)
FROM tablex
WHERE field6 is null AND field2 = #field2 AND field3 = #field3 AND field5 = #field5
)
)
begin
exec cred.Demobilize(#field0, #field1);
end;
In practice, I think this would more commonly be written using not exists:
IF (not exists (SELECT 1
FROM tablex
WHERE field6 is null AND field2 = #field2 AND field3 = #field3 AND field5 = #field5
)
)
begin
exec cred.Demobilize(#field0, #field1);
end;
The not exists version can be faster, because the first row encountered will satisfy the condition clause. The count(*) version has to find all matching rows and count them.
Related
I have a table where field2 sometimes consists of data and sometimes consists of CASE Expressions embedded in the cell. I'd like field3 to equal field2 when field2 has data, but I'd like field3 to return the result of the Case Expression when the Case Expression is embedded in field2, like this:
field1 field2 field3
A Data Data
A Data Data
B Data Data
B Case Exp.. Result of Case Exp
B Data Data
Here's my current method:
Declare #field2variable as NVARCHAR(max);
Select #field2variable=t.field2 From table;
Select
t.field1,
t.field2,
Case When t.field2 NOT Like '%Data%' Then EXECUTE SP_EXECUTESQL #field2variable
Else t.field2
End As field3
Into new_table
From table t
The first problem is that I'm trying to assign #field2variable to an entire column instead of a single value.
The second problem is that it SQL won't let me run "EXECUTE SP_EXECUTESQL" in the select statement.
if you need to have that table you should create that like this :
Declare #field2variable as NVARCHAR(max);
declare #coun int;
select #coun=count(id) from table;
declare #idd int =0;
declare #bb nvarchar(50);
while #coun>0
begin
set #idd=(select id from ( select id,ROW_NUMBER() over(order by id) as rowss from table )as a where rowss=#coun)
set #bb=cast(( select field2 from table where id=#idd)as nvarchar(50))
if(left(#bb,1)<>'D')
exec SP_EXECUTESQL #bb
set #coun=#coun-1;
--insert into table ......
end
at the end you should create your table and insert the result of this into that table
Recently I have had to do a few variable updates to a table, and although I am aware of the MERGE statement (although need to catch up on all of that!), I also performed the following statement to optional update a table and wish to check if this is "a good idea" or has some hidden consequences that I not aware of.
So in my case, I pass a primary key to a table, however depending on if parameters passed are null or not, I update the column.. obviously if you had to ensure a forceful update (of a status etc.) then you would just update the column.. this is to save having multiple "IF / THEN" type structures..
create procedure sp_myprocedure
as
#id bigint,
#field1 int = null,
#field2 varchar(255) = null,
#field3 char(1) = null
begin
update my_table
set
field1 = case when #field1 is not null then #field1 else field1 end,
field2 = case when #field2 is not null then #field2 else field2 end,
field3 = case when #field3 is not null then #field3 else field3 end,
where
id = #id
end
Just after some thoughts of the above or is it best to pursue the MERGE statement for scenarios like the above?
Many thanks in advance,
This is fine although it can be written in a cleaner way.
update my_table
set
field1 = coalesce (#field1,field1)
,field2 = coalesce (#field2,field2)
,field3 = coalesce (#field3,field3)
where
id = #id and coalesce(#field1,#field2,#field3) is not null
You can also move the coalesce(#field1,#field2,#field3) is not null to a wrapper block
if coalesce(#field1,#field2,#field3) is not null
begin
update my_table
set
field1 = coalesce (#field1,field1)
,field2 = coalesce (#field2,field2)
,field3 = coalesce (#field3,field3)
where
id = #id
end
MERGE statement is not relevant here.
With MERGE the decision is if to INSERT, UPDATE or DELETE a record base on the non-existent/existent of a record with the same merge keys in the source/target table.
In your case it is always UPDATE.
create procedure sp_myprocedure
#id bigint,
#field1 int = null,
#field2 varchar(255) = null,
#field3 char(1) = null
as
begin
IF coalesce(#field1,#field2,#field3) is not null
update dbo.my_table
set
field1 = coalesce (#field1,field1),
field2 = coalesce (#field2,field2),
field3 = coalesce (#field3,field3)
where id = #id
END
Responding to the answer by #Dudu Markovitz:
MERGE statement is not relevant here.
I disagree , I think MERGE is entirely relevant here.
The idea is to create a source table expression using the parameter values with which to update the target table:
MERGE my_table T
USING ( VALUES ( #id, #field1, #field2, #field3 ) )
AS S ( id, field1, field2, field3 )
ON T.id = S.id
WHEN MATCHED THEN
UPDATE
SET field1 = COALESCE( S.field1, T.field1 ),
field2 = COALESCE( S.field2, T.field2 ),
field3 = COALESCE( S.field3, T.field3 );
Of course, if there was a single table-valued parameter (as arguable there should be) then the relevance of MERGE is even more obvious.
Hi guys I have a pl/sql cursor that takes too long to execute. I want to know how can I make the same process but with better performance and probably better code. I am new to PL/SQL.
Declare
Cursor Cursor1 is
select * from table1 where
field1 IS NULL
or
field2 IS NULL or field3 IS NULL or field4 is null or field5 IS NULL or field6 IS NULL;
Begin
For i in Cursor1 loop
if i.field1 IS NULL then
update table1 set field1=0 where recordId=i.recordId;
end if;
if i.field2 IS NULL then
update table1 set field2=0 where recordId=i.recordId;
end if;
if i.field3 IS NULL then
update table1 set field3=0 where recordId=i.recordId;
end if;
if i.field4 IS NULL then
update table1 set field4=0 where recordId=i.recordId;
end if;
if i.field5 IS NULL then
update table1 set field5=0 where recordId=i.recordId;
end if;
if i.field6 IS NULL then
update table1 set field6=0 where recordId=i.recordId;
end if;
End loop;
End;
The question basically is how can I update a field of one specific record, taking into account the conditions of the field. The thing is that the update can occur in the same record many times if the condition apply for many fields in the record.
Thanks...
It's possible to do the same with one UPDATE
UPDATE table1 SET
field1 = COALESCE(field1, 0)
, field2 = COALESCE(field2, 0)
, field3 = COALESCE(field3, 0)
, field4 = COALESCE(field4, 0)
, field5 = COALESCE(field5, 0)
, field6 = COALESCE(field6, 0)
WHERE field1 IS NULL OR field2 IS NULL OR field3 IS NULL
OR field4 IS NULL OR field5 IS NULL OR field6 IS NULL
Here's another take on this:
UPDATE TABLE1
SET FIELD1 = NVL(FIELD1, 0),
FIELD2 = NVL(FIELD2, 0),
FIELD3 = NVL(FIELD3, 0),
FIELD4 = NVL(FIELD4, 0),
FIELD5 = NVL(FIELD5, 0),
FIELD6 = NVL(FIELD6, 0);
Rationale: any query which performs this update is going to do a full table scan anyways because it's looking for NULLs, which won't be indexed in the usual case, and even if they ARE indexed there's a fair chance the optimizer will choose a full table scan anyways. Why waste time checking six different fields for NULLs?
Share and enjoy.
Try executing couple of updates like this, avoiding the usage of a cursor:
update table1 set field1=0 where field1 IS NULL;
update table1 set field2=0 where field2 IS NULL;
update table1 set field3=0 where field3 IS NULL;
update table1 set field4=0 where field4 IS NULL;
update table1 set field5=0 where field5 IS NULL;
update table1 set field6=0 where field6 IS NULL;
I don't think that there is a more efficient way to do this.
Ok, so I've learned from other posts/sites, that the following style of query will execute atomically:
INSERT INTO Foo(field1, field2)
SELECT #field1, #field2
WHERE NOT EXISTS (SELECT * FROM Foo
WHERE Field1 = #field1
OR Field2 = #field2)
This would be used to satisfy a design requirement that both field1 and field2 be unique. So far, all is fine and dandy.
BUT, in the case of such a record already existing (where the query inserts 0 rows) what if I want to know WHICH field already had a record with the same value. (i.e., which of the following statements are true?
there was already an existing record where Field1 = #field1
there was already an existing record where Field2 = #field2
both of the above
You would need to know which field is at fault in order to show an error message that tells the user which field they need to change to a unique value. I could always check with a second query, but that would not be atomic. The data may have changed between the attempted insert and the 2nd query to determine which field was at fault, and the error message may not reflect the actual state of the DB.
Any ideas on how to handle this case?
Assumptions:
You expect most INSERTs to succeed.
You have a unique contraint such that a bad INSERT will fail.
You aren't concerned about matching NULLs.
set transaction isolation level serializable;
begin transaction;
begin try
insert into Foo ( Field1, Field2 ) values ( #Field1, #Field2 );
end try
begin catch
-- Really ought to confirm that the error was the expected one here.
select
#Field1Match = case when Field1 = #Field1 then Cast( 1 as Bit ) else Cast( 0 as Bit ) end,
#Field2Match = case when Field2 = #Field2 then Cast( 1 as Bit ) else Cast( 0 as Bit ) end
from Foo
where Field1 = #Field1 or Field2 = #Field2;
end catch;
commit transaction;
Based on my research (here & here), unless you have a very high confidence that over 95% of the inserts will succeed, I would use the opposite approach as HABO. Borrowing from the same assumption that you aren't concerned about matching NULLs:
DECLARE #Col1Match VARCHAR(20), #Col2Match VARCHAR(20), #msg NVARCHAR(4000);
SET ANSI_WARNINGS OFF;
BEGIN TRANSACTION;
SELECT #Col1Match = MAX(CASE Field1 WHEN #Field1 THEN 'Field1 exists:' END),
#Col2Match = MAX(CASE Field2 WHEN #Field2 THEN 'Field2 exists:' END)
FROM dbo.Foo WITH (HOLDLOCK)
WHERE Field1 = #Field1 OR Field2 = #Field2;
IF #Col1Match IS NULL AND #Col2Match IS NULL
BEGIN
INSERT dbo.Foo(Field1, Field2) SELECT #Field1, #Field2;
END
ELSE
BEGIN
SET #msg = LTRIM(COALESCE(' ' + #Col1Match + ' (' + #Field1 + ')', '')
+ COALESCE(' ' + #Col2Match + ' (' + #Field2 + ')', ''));
END
COMMIT TRANSACTION;
IF #msg IS NOT NULL
BEGIN
RAISERROR(#msg, 11, 1);
END
I have a stored procedure where I am passing a value to be used in the select statement in the where clause.
If the value that I am passing is NULL, I do not want it to be part of that portion of the where clause where it is used. In the example below, variable2 is the variable I am passing to the stored procedure and using in the sql statement but if #variable2 is NULL, I do not want to use variable2= #val1 in the where clause. Example:
select Field1, Field2 from tbl1
where variable2= #val1
and ID = 'test'
Try:
where (#val1 is null or variable2 = #val1)
and ID = 'test'
select Field1, Field2 from tbl1
where (variable2= #val1 or #val1 is null)
and ID = 'test'
How about:
select Field1, Field2 from tbl1
where (#val1 IS NULL or variable2 = #val1)
and ID = 'test'
Your WHERE clause should have the column on the left side, and that could possibly be the case but you are calling it variable2. This would work, given specific parameters:
select Field1, Field2
from tbl1
where yourColumn =
case
when #param1 is null
then #param2
end
I have used a generic field name and parameter names, but you should get the idea.