I want to update FirstTable from SecondTable, but there are many complications.
This is the main query:
UPDATE x.FirstTable Table1
set Table1.UpdatedColumn = (
SELECT Table2.V_PROD_CODE
FROM y.SecondTable Table2
WHERE Table2.XX_V_ACCOUNT_ID1 = Table1.XX_V_ACCOUNT_ID1
AND Table2.XX_V_ACCOUNT_ID2 = Table1.XX_V_ACCOUNT_ID2
AND Table2.XX_V_ACCOUNT_ID3 = Table1.XX_V_ACCOUNT_ID3
AND Table2.c_Date between '17-Apr-2018' and '27-Apr-2018'
AND Table2.c_DATE = Table1.c_date)
WHERE Table1.c_date between '17-Apr-2018' and '27-Apr-2018'
AND length(Table1.xx_v_account_id1) = 12;
It is taking too long, so I thought about creating a cursor:
create or replace procedure wco as
cursor UpdateCursor is
SELECT Table2.V_PROD_CODE
FROM y.SecondTable Table2
INNER JOIN x.FirstTable Table1 on SUBSTR(Table1.V_CAST_REF_CODE, 6, 8) = SUBSTR(Table2.V_CAST_REF_CODE, 6, 8)
WHERE Table2.XX_PRODUCT_CODECCOUNT_ID1 = Table1.XX_PRODUCT_CODECCOUNT_ID1
AND Table2.XX_PRODUCT_CODECCOUNT_ID2 = Table1.XX_PRODUCT_CODECCOUNT_ID2
AND Table2.XX_PRODUCT_CODECCOUNT_ID3 = Table1.XX_PRODUCT_CODECCOUNT_ID3
AND Table2.fic_mis_date between '17-Apr-2018' and '27-Apr-2018'
AND Table2.c_DATE = Table1.c_date
for update;
v_PRODUCT_CODE Table2.V_PROD_CODE%type;
begin
open UpdateCursor;
loop
fetch UpdateCursor into v_PRODUCT_CODE;
exit when UpdateCursor%notfound;
update XXBADWH.xxba_dwh_instrument_master INST
set INST.v_product_code = v_PRODUCT_CODE
WHERE current of UpdateCursor
AND INST.fic_mis_date between '17-Apr-2018' and '27-Apr-2018'
AND length (INST.xx_v_account_id1) = 12;
end loop;
close UpdateCursor;
end;
exec wco;
drop procedure wco;
What is wrong with the query? and any better practices?
For this query:
UPDATE x.FirstTable Table1
SET Table1.UpdatedColumn = (
SELECT Table2.V_PROD_CODE
FROM y.SecondTable Table2
WHERE Table2.XX_V_ACCOUNT_ID1 = Table1.XX_V_ACCOUNT_ID1 AND
Table2.XX_V_ACCOUNT_ID2 = Table1.XX_V_ACCOUNT_ID2 AND
Table2.XX_V_ACCOUNT_ID3 = Table1.XX_V_ACCOUNT_ID3 AND
Table2.c_Date between DATE '2018-04-17' and DATE '2018-04-27' AND
Table2.c_DATE = Table1.c_date
)
WHERE Table1.c_date between DATE '2018-04-17' and DATE '2018-04-27' AND
length(Table1.xx_v_account_id1) = 12;
You want indexes on Table1(length(xx_v_account_id1), c_date) and Table2(XX_V_ACCOUNT_ID1, XX_V_ACCOUNT_ID2, XX_V_ACCOUNT_ID3, c_DATE).
I would start with the indexes (tested on a select select statement). Cursors are rarely the route to better performance.
Related
I am trying to execute this query with some 'conditional logic', it is my first attempt doing something like this in databases.
Here is the code:
DECLARE #iddevice INT;
SET #iddevice = 15;
IF(#iddevice = 15 AND DEVICEATTRIBUTES.DEVICEATTRIBUTE = 'PortA')
BEGIN
UPDATE DEVICEATTRIBUTES
SET VALUE = '4701'
WHERE IDDEVICE = 15 AND DEVICEATTRIBUTES.DEVICEATTRIBUTE = 'PortA'
END
IF(#iddevice = 15 AND DEVICEATTRIBUTES.DEVICEATTRIBUTE = 'PortB')
BEGIN
UPDATE DEVICEATTRIBUTES
SET VALUE = '4711'
WHERE IDDEVICE = 15 AND DEVICEATTRIBUTES.DEVICEATTRIBUTE = 'PortB'
END
IF(#iddevice = 15 AND DEVICEATTRIBUTES.DEVICEATTRIBUTE = 'IP')
BEGIN
UPDATE DEVICEATTRIBUTES
SET VALUE = '172.19.106.201'
WHERE IDDEVICE = 15 AND DEVICEATTRIBUTES.DEVICEATTRIBUTE = 'IP'
END;
GO
I am aware that something with the syntax is wrong, my question is ... how can I add DEVICEATTRIBUTES.DEVICEATTRIBUTE inside the 'if' clause?
You script you can re-write as follow:
DECLARE #iddevice INT;
SET #iddevice = 15;
UPDATE DEVICEATTRIBUTES
SET VALUE =
CASE
WHEN DEVICEATTRIBUTES.DEVICEATTRIBUTE = 'PortA' THEN '4701'
WHEN DEVICEATTRIBUTES.DEVICEATTRIBUTE = 'PortB' THEN '4711'
WHEN DEVICEATTRIBUTES.DEVICEATTRIBUTE = 'IP' THEN '172.19.106.201'
END
WHERE IDDEVICE = #iddevice AND DEVICEATTRIBUTES.DEVICEATTRIBUTE IN ('PortA', 'PortB', 'IP')
In SQL Server, you can use UPDATE with JOIN:
UPDATE DA
SET VALUE = '4701'
FROM DEVICEATTRIBUTES DA JOIN
(VALUES ('PortA', '4701'),
('PortB', '4711'),
('IP', '172.19.106.201')
) V(DEVICEATTRIBUTE, VALUE)
ON DA.DEVICEATTRIBUTE = V.DEVICEATTRIBUTE
WHERE IDDEVICE = 15;
The VALUES clause is a handy way to add in the values you want to change -- and it reduces the risk of typos.
However, in your code, you can just use three UPDATEs. The IF statements are not necessary. If no rows match the WHERE clause then no rows are updated.
I need to optimize the Procedure below. Syntax should be in Informix.
Here a table update is required with sequential update. It seems to be very large.Can it be optimized.
CREATE OR REPLACE PROCEDURE ENTRY() LANGUAGE SQL
BEGIN ATOMIC
DECLARE record integer;
DECLARE txaa_id bigint;
DECLARE id bigint;
DECLARE createDatetimed timestamp;
DECLARE idPlus bigint;
set record = 0;--
set txaa_id = 0;--
set id = 0;--
set idPlus = 0;--
set createDatetimed = null;--
FOR v_row1 as select distinct txaa_id from finalBaseData
DO
FOR v_row2 as select txsa_id , finalBaseData.txaa_id , finalBaseData.createdatetime from tx_status_audit,finalBaseData where tx_status_audit.txaa_id = v_row1.txaa_id and tx_status_audit.txaa_id = finalBaseData.txaa_id and tx_status_audit.cdts = 'OUT' order by tx_status_audit.create_datetime desc fetch first 1 rows only
DO
set record = record + 1;
IF ( record = 1)
THEN
set id = v_row2.txsa_id;
set idPlus = id + 1;
set txaa_id = v_row2.txaa_id;
set createDatetimed = v_row2.createdatetime;
END IF;
END FOR;
insert into tx_status_audit values (idPlus,'CMPT',txaa_id,'HWNG',createDatetimed);
set record = 0;
set idPlus = 0;
set txaa_id = 0;
set createDatetimed = null;
END FOR;
END;
I converting this Oracle trigger to SQL Server. In Oracle there are using if condition for updating a table. I was wondering is it necessary to use if statement in SQL Server. I'm thinking to use in where clause. Please let me know if that's correct?
Thanks
CREATE OR REPLACE TRIGGER "DB1"."TG_PG_CODES"
BEFORE UPDATE OF "str_number", "op_status"
ON "DB1"."Header_T"
REFERENCING OLD AS oldrow NEW AS newrow
FOR EACH ROW
BEGIN
IF :newrow.op_status = 'X'
THEN
UPDATE DB1.pg_pollutant
SET op_status = 'X',
str_comp_status = '98',
str_mod_person = '3327'
WHERE str_number = :newrow.str_number;
END IF;
IF :newrow.op_status <> 'X'
AND SUBSTR (:oldrow.str_pgcodes, 1, 1) = '1'
AND SUBSTR (:newrow.str_pgcodes, 1, 1) = '0'
THEN
UPDATE DB1.pg_pollutant
SET op_status = 'X',
str_comp_status = '98'
WHERE str_number = :newrow.str_number
AND str_pollutant_key = :newrow.str_number || '0';
END IF;
END;
=============================================
In sql server
CREATE TRIGGER [dbo].[TG_TG_PG_CODES] ON [dbo].[Header_T]
AFTER UPDATE
AS
IF(UPDATE(str_number)
OR UPDATE(op_status))
BEGIN
IF(
(
SELECT op_status
FROM inserted
) = 'X')
BEGIN
UPDATE a
SET
a.op_status = 'X',
a.str_comp_status = '98',
a.str_mod_person = '3327'
FROM DB1.pg_pollutant a
INNER JOIN inserted AS i ON a.str_number = i.str_number;
END;
UPDATE a
SET
a.op_status = 'X',
a.str_comp_status = '98'
FROM DB1.pg_pollutant a
INNER JOIN inserted AS i ON a.[str_number] = i.[str_number]
AND a.str_pollutant_key = i.[str_number]+'0'
INNER JOIN Deleted AS d ON a.[str_number] = d.[str_number]
WHERE i.stroperationalstatus <> 'X'
AND SUBSTRING(d.str_pgcodes, 1, 1) = '1'
AND SUBSTRING(i.str_pgcodes, 1, 1) = '0'; /* I used this condition in where clause */
END;
I have a VB.NET application that is creating some INSERT, UPDATE, DELETE statements based on the users selections. I can tell that the SQL is being successfully executed on SQL Server 2008 (I see the table records adjusting appropriately), except one of my insert triggers is not firing.
SQL generated by the application code:
insert into [RECLASS_BALANCE_ADJSTMNT]( PRGRM_REC_ID, DEDUCTN_REC_ID, RBA_YR_PD_NUM, RBA_AMOUNT, RBA_TYPE, ADJUSTER_USER_ID )
values (5504, 8154, dbo.getCurrentYrPdNum(), abs(-21510.70), 'M', '10139638');
insert into [MATCH] (DEDUCTN_REC_ID, PRGRM_REC_ID, YR_PD_NUM, MATCH_TYPE_FLG)
values (8154, 5504, dbo.getCurrentYrPdNum(), 'M');
delete from [POTENTIAL_MATCH]
where deductn_rec_id = 8154
and prgrm_rec_id = 5504;
update [PROGRAM_GL_DTL]
set MATCH_FLG = 'Y', MATCH_FLG_MODIFIED_TIMESTAMP = getdate()
where PRGRM_REC_ID = 5504;
update [DEDUCTION]
set MATCH_FLG = MATCH_FLG + 1
where DEDUCTN_REC_ID = 8154;
INSERT trigger:
CREATE TRIGGER [dbo].[check_partial_offset_status]
ON [dbo].[RECLASS_BALANCE_ADJSTMNT]
FOR INSERT
AS
BEGIN
DECLARE #deductnRecId int;
DECLARE #deductnBalance decimal(18,2);
DECLARE #deductnOriginalAmount decimal(18,2);
SELECT #deductnRecId = i.deductn_rec_id FROM inserted i;
SELECT #deductnBalance = ds.ytd_amt, #deductnOriginalAmount = ds.original_invoice_amount
FROM deduction_summary_updt ds
WHERE ds.deductn_rec_id = #deductnRecId;
IF ABS(#deductnBalance) > 0
BEGIN
UPDATE deduction
SET comment_id = 12
WHERE deductn_rec_id = #deductnRecId;
END --partial matched
IF #deductnBalance = #deductnOriginalAmount
BEGIN
UPDATE deduction
SET comment_id = 6
WHERE deductn_rec_id = #deductnRecId;
END --unmatched
IF #deductnBalance = 0
BEGIN
UPDATE deduction
SET comment_id = 9
WHERE deductn_rec_id = #deductnRecId;
END --fully matched
DECLARE #prgrmRecId int;
DECLARE #prgrmBalance decimal(18,2);
DECLARE #prgrmOriginalAmount decimal(18,2);
SELECT #prgrmRecId = i.prgrm_rec_id FROM inserted i;
SELECT #prgrmBalance = rs.ytd_amt, #prgrmOriginalAmount = rs.reclass_amount
FROM reclass_summary rs
WHERE rs.prgrm_rec_id = #prgrmRecId;
IF ABS(#prgrmBalance) > 0
BEGIN
UPDATE program_gl_dtl
SET comment_id = 12
WHERE prgrm_rec_id = #prgrmRecId;
END --partial matched
IF #prgrmBalance = #prgrmOriginalAmount
BEGIN
UPDATE program_gl_dtl
SET comment_id = 5
WHERE prgrm_rec_id = #prgrmRecId;
END --unmatched
IF #prgrmBalance = 0
BEGIN
UPDATE program_gl_dtl
SET comment_id = 10
WHERE prgrm_rec_id = #prgrmRecId;
END --fully matched
END
GO
I'm trying to understand why the "INSERT INTO [RECLASS_BALANCE_ADJSTMNT].." generated by the application code does not cause the trigger to fire.
I appreciate any help. Thanks!
I have a trigger called "updateFriendlyURLTitle" in dbo.Aritcle table. When a individual article inserted, that trigger working fine.
But in article importing process: I've used the following codes. This codes make copy article but it doesn't fire the trigger to generate FriendlyUrl.
private void WriteArticlesToDatabase<TData>(DataSet ds, SqlTableDetails tableDetails, IEnumerable<TData> newArticles, SqlTransaction transaction)
{
var dt = WriteToDataTable(ds, tableDetails.Table, newArticles);
using (var bulkCopy = new SqlBulkCopy(_destConnection, SqlBulkCopyOptions.FireTriggers, transaction))
{
bulkCopy.DestinationTableName = tableDetails.ToString();
bulkCopy.WriteToServer(dt);
}
}
My trigger is like below:
ALTER TRIGGER [dbo].[updateFriendlyURLTitle] ON [dbo].[Articles]
AFTER INSERT, UPDATE
AS
IF ##ROWCOUNT > 0
BEGIN
IF COLUMNS_UPDATED() != 0x0000200000100000 -- columns other than newsCounterViews have been updated
BEGIN
DECLARE #oldestfulllucenebuild AS DATETIME
DECLARE #deletedNewsID INT
DECLARE #newsStatus BIT
DECLARE #maxcalcimp AS FLOAT
DECLARE #insertedCalculatedImportance INT
DECLARE #insertedNormalisedCalculatedImportance INT
DECLARE #insertedSeoURLTitle VARCHAR(255)
select #oldestfulllucenebuild = min(luceneIndexCreatedDate)
from Lucene_Indexes
where luceneIndexType = 'news'
select #oldestfulllucenebuild = dateAdd(year,10,#oldestfulllucenebuild)
select #maxcalcimp = cast(#oldestfulllucenebuild as float) * 48 *100 --the max importance
select #insertedCalculatedImportance = inserted.newsCalculatedImportance,
#insertedNormalisedCalculatedImportance = inserted.newsNormalisedCalculatedImportance,
#insertedSeoURLTitle = inserted.newsSeoURLTitle
from inserted
--if the current statement is updating the importance or seo columns then do not perform this query (so it doesn't get stuck in a loop)
IF (NOT UPDATE(newsCalculatedImportance)) AND (NOT UPDATE(newsNormalisedCalculatedImportance)) AND (NOT UPDATE(newsSeoURLTitle))
OR
--if it is inserting a new record then perform the query
(#insertedCalculatedImportance = 0 AND #insertedNormalisedCalculatedImportance is null AND #insertedSeoURLTitle = '')
BEGIN
update Articles
set newsCalculatedImportance = cast(cast(inserted.newsArticledate as float )*48 + inserted.newsimportance AS int)
, newsNormalisedCalculatedImportance = (1/ #maxcalcimp) * cast(cast(inserted.newsArticledate as float )*48 + inserted.newsimportance AS int)
, newsSeoURLTitle = LEFT(dbo.getSEOURLTitle(inserted.newstitle), 255)
from Articles inner join inserted on
Articles.newsid = inserted.newsid
END
SELECT #deletedNewsID = newsID, #newsStatus = newsStatus
FROM inserted
IF(#newsStatus = 0)
BEGIN
DELETE FROM tbl_DenormalisedNews WHERE newsid = #deletedNewsID
DELETE FROM News_Deleted_DateTime
WHERE NewsID = #deletedNewsID
INSERT INTO News_Deleted_DateTime
VALUES (#deletedNewsID, getDate())
END
ELSE
BEGIN
--news status is 1, remove it from the news_deleted_datetime table if it exists
DELETE FROM News_Deleted_DateTime
WHERE NewsID = #deletedNewsID
END
-- newsImage1 optimisation: if newsImage1 = '' THEN has_image = FALSE ELSE has_image = TRUE
IF UPDATE(newsImage1)
UPDATE Articles SET
has_image = CASE WHEN Articles.newsImage1 = '' THEN CAST(0 AS bit) ELSE CAST(1 AS bit) END
FROM
Articles INNER JOIN inserted ON Articles.newsid = inserted.newsid
END
END
Does anyone knows how to fix this issue ?