SQL server UPDATE OPENQUERY - sql-server

I am trying to link two servers (the host is SQL Server 2008 and the destination is ORACLE) so that a table on the oracle server is populated by data held in multiple tables on the SQL server.
I have set up an INSERT OPENQUERY, which works perfectly fine. I also want to setup another query to update those records.
So, my insert query, selects records created in the last 24 hours, and inserts them, no problem. But I am struggling to create an UPDATE OPENQUERY script, that will run every 24 hours to make the relevant changes.
Here is my INSERT
INSERT OPENQUERY(ukdev662, 'SELECT DOCKET_NUMBER,
APP_NUMBER,
ATT,
LIT_H,
REVIEW,
COUNTRY,
NOTICE,
COUNTRY_CODE,
FORMALITY_NAME
FROM GWDMDV29.LOOKUPS__IPMANAGER')
SELECT PMasters.DocketNumber + ISNULL(Codes_RelationType.Code, '') + ISNULL(PMasters.FilingNumber, '') + 'PTE'
,ISNULL(PMasters.AppNumber, '[null]')
,ISNULL(PartyDetails_Att.Party, 'Att not assigned')
,0
,CONVERT(DATETIME, '20130128')
,uktst1633.dbo.Countries.Description
,'Preserve'
,uktst1633.dbo.Countries.WIPO
,ISNULL(PartyDetails_Associate.Party, '[null]')
FROM uktst1633.dbo.Countries
RIGHT OUTER JOIN uktst1633.dbo.PatentMasters PMasters
ON ( PMasters.Country = uktst1633.dbo.Countries.CountryID )
INNER JOIN uktst1633.dbo.Codes Codes_CType
ON ( PMasters.CType = Codes_CType.CodeID
AND Codes_CType.CodeTypeID = 'CSP'
)
INNER JOIN uktst1633.dbo.Codes Codes_RelationType
ON ( Codes_RelationType.CodeID = PMasters.RelationType
AND Codes_RelationType.CodeTypeID = 'RLP'
)
LEFT OUTER JOIN uktst1633.dbo.Parties Parties_Att
ON ( Parties_Att.PartyID = PMasters.Att
AND ( Parties_Att.PartyTypeID = 'ATP'
OR Parties_Att.PartyTypeID IS NULL
)
)
LEFT OUTER JOIN uktst1633.dbo.PartyDetails PartyDetails_Att
ON ( PartyDetails_Att.PartyDetailID = Parties_Att.PartyDetailID )
LEFT OUTER JOIN uktst1633.dbo.Parties Parties_Associate
ON ( Parties_Associate.PartyID = PMasters.Associate
AND ( Parties_Associate.PartyTypeID = 'AGP'
OR Parties_Associate.PartyTypeID IS NULL
)
)
LEFT OUTER JOIN uktst1633.dbo.PartyDetails PartyDetails_Associate
ON ( PartyDetails_Associate.PartyDetailID = Parties_Associate.PartyDetailID )
WHERE ( ( Codes_RelationType.Description = 'CONTINUATION'
OR Codes_RelationType.Description = 'DIVISION'
)
AND Codes_CType.Description = 'Regular'
AND PMasters.CreateDate >= DATEADD(day, -1, GETDATE())
)
Thanks for any help . I have searched around and cannot find much on OPENQUERY, it all seems to be pretty basic stuff. I tried following this syntax's examples but it got me nowhere...
UPDATE
Table
SET
Table.col1 = other_table.col1,
Table.col2 = other_table.col2
FROM
Table
INNER JOIN
other_table
ON
Table.id = other_table.id

Related

SQL Query to get data from various databases

I wrote the below query to pull the data from different databases. I have created two temp tables to pull the data from two different databases and finally a select statement from the original database to join all the tables. My query is getting executed but not getting any data.(Report is blank). I tried executing the two temp tables separately. it is giving the correct data. But when I execute the whole query, the result is blank. Below is the query. Please help.
"set fmtonly off
use GODSDB
IF object_id('tempdb..#CISIS_Call_Log') IS NOT NULL DROP TABLE #CISIS_Call_Log
select *
into #CISIS_Call_Log
from OPENQUERY (CSISDB,
'select
ccl.ContractOID,
ccl.db_insertdate,
ccl.ContractCallLogStatusIdentifier,
ccl.db_UpdateDate,
ccp.ContractCallLogPurposeOID,
ccp.ContractCallLogPurposeIdentifier,
ccp.Description
from csisdb.dbo.ContractCallLog CCL
inner join csisdb.dbo.ContractCallLogPurpose CCP on ccl.ContractCallLogPurposeIdentifier = ccp.ContractCallLogPurposeIdentifier
where JurisdictionShortIdentifier = ''ON''
AND ContractCallLogStatusIdentifier IN (''DNR'', ''NR'')
')
IF object_id('tempdb..#CMS_Campaign') IS NOT NULL DROP TABLE #CMS_Campaign
select *
into #CMS_Campaign
from OPENQUERY (BA_GBASSTOCMS, '
Select
SystemSourceIdentifier,
ContractOID,
OfferSentDate,
CampaignOfferTypeIdentifier,
CampaignContractStatusIdentifier,
CampaignContractStatusUpdateDate,
DeclineDate,
CampaignOfferOID,
CampaignOID,
CampaignStartDate,
CampaignEndDate,
Jurisdiction,
CampaignDescription
from CMS.dbo.vw_CampaignInfo
where Jurisdiction = ''ON''
and CampaignOfferTypeIdentifier = ''REN''
')
select mp.CommodityTypeIdentifier as Commodity
,c.RtlrContractIdentifier as ContractID
,cs.ContractStatusIdentifier as ContractStatus
,c.SigningDate
,cf.StartDate as FlowStartDate
,cf.EndDate as FlowEndDate
,datediff(day, getdate(), c.RenewalDate) as RemainingDays
,c.RenewalDate
,l.ContractCallLogStatusIdentifier as CallLogType
,Substring (l.Description, 1, 20) as CallPurpose
,l.db_insertDate as CallLogDate
,cms.CampaignOfferOID as OfferID
,cms.CampaignContractStatusIdentifier as OfferStatus
,cms.CampaignContractStatusUpdateDate as StatusChangeDate
,cms.DeclineDate
from Contract c
inner join contractstate cs on cs.contractoid = c.ContractOID
and cs.ContractStatusIdentifier in ('ERA', 'FLW')
and datediff(day, getdate(), c.RenewalDate) > 60
inner join SiteIdentification si on si.SiteOID = c.SiteOID
inner join MarketParticipant mp on mp.MarketParticipantOID = si.MarketParticipantOID
inner join Market m on m.MarketOID = mp.MarketOID
inner join Jurisdiction j on j.JurisdictionOID = m.JurisdictionOID
and j.CountryCode = 'CA'
and j.ProvinceOrStateCode = 'ON'
inner join ContractFlow cf on cf.ContractOID = c.ContractOID
inner join #CISIS_Call_Log l on convert(varchar(15), l.ContractOID) = c.RtlrContractIdentifier
inner join #CMS_Campaign cms on convert(varchar(15), cms.ContractOID) = c.RtlrContractIdentifier
set fmtonly on"
IF the data in each temp table is verified, then:
Try a smaller, less complex, query to test your temp tables with. Also try them using a LEFT join as well e.g.:
select
c.RtlrContractIdentifier as ContractID
, c.SigningDate
, datediff(day, getdate(), c.RenewalDate) as RemainingDays
, c.RenewalDate
, l.ContractCallLogStatusIdentifier as CallLogType
, Substring (l.Description, 1, 20) as CallPurpose
, l.db_insertDate as CallLogDate
, cms.CampaignOfferOID as OfferID
, cms.CampaignContractStatusIdentifier as OfferStatus
, cms.CampaignContractStatusUpdateDate as StatusChangeDate
, cms.DeclineDate
from Contract c
LEFT join #CISIS_Call_Log l on convert(varchar(15), l.ContractOID) = c.RtlrContractIdentifier
LEFT join #CMS_Campaign cms on convert(varchar(15), cms.ContractOID) = c.RtlrContractIdentifier
Does this return data? Does it return data from both joined tables?
If neither temp table is returning data then those join conditions need to be changed.
If both temp tables do return data from that query, then try INNER joins. If that still works, then add back more joins (one at a time) until you identify the join that causes the overall fault.
Without data for every table it just isn't possible for us to pinpoint the exact reason for a NULL result. Only you can, so you need to trouble-shoot the problem one step at a time.

SQL Conditional Merge When Matched Update when columns do not equal

I have a table named SalesOrders. I merge data form multiple tables into it. Within this table, I have a column named Ack which will toggle to 'N' when the row is inserted or updated (I toggle 'Y' in C# code). the trouble I'm having is when I run my query, I only want Ack to change to 'N' when something changes. I tried adding conditions in the WHEN MATCHED statement but the table never updates when there is a change.
MERGE QA.dbo.SalesOrders AS TARGET USING(SELECT SOD.ORDNUM_28 +
LINNUM_28 + DELNUM_28 AS [SalesOrd], SOD.PRTNUM_28, PM.PMDES1_01,
SOD.CURDUE_28, SOD.DUEQTY_28, CPD.CUSTPRT_103, SOM.CUSTPO_27,
CPD.UDFREF_103, CPD.PRTNUM_103,SOD.CreationDate, CM.EMAIL1_23, SOD.ORDNUM_28
FROM SO_Detail AS SOD FULL OUTER JOIN
Customer_Part_Data AS CPD ON SOD.PRTNUM_28 = CPD.PRTNUM_103 FULL OUTER JOIN
SO_Master AS SOM ON SOD.ORDNUM_28 = SOM.ORDNUM_27 FULL OUTER JOIN
Part_Master AS PM ON SOD.PRTNUM_28 = PM.PRTNUM_01 FULL OUTER JOIN
Customer_Master AS CM ON SOD.CUSTID_28 = CUSTID_23
WHERE (STATUS_28 = '3') AND (SOD.CreationDate > '09 / 14 / 2017') AND
(CUSTPO_27 <> ' ') AND (SOM.STYPE_27 = 'CU')
AND (SOD.STK_28 NOT LIKE '%RMA%') AND (SOD.STYPE_28 = 'CU')) SOURCE
ON OrderNum = SOURCE.SalesOrd
WHEN MATCHED AND PartNum <> SOURCE.PRTNUM_28 OR Description <>
SOURCE.PMDES1_01 OR DueQty <> SOURCE.DUEQTY_28 OR CustPartNum <>
SOURCE.CUSTPRT_103 OR CustPo <> SOURCE.CUSTPO_27 OR CustRev <>
SOURCE.UDFREF_103 OR ShipDate <> SOURCE.CURDUE_28 OR email <>
SOURCE.EMAIL1_23 // This does not work
THEN
UPDATE
SET PartNum = SOURCE.PRTNUM_28, Description =
SOURCE.PMDES1_01, DueQty = SOURCE.DUEQTY_28, CustPartNum =
SOURCE.CUSTPRT_103, CustPo = SOURCE.CUSTPO_27, CustRev =
SOURCE.UDFREF_103, ShipDate = SOURCE.CURDUE_28, email = SOURCE.EMAIL1_23,
OrgDate = SOURCE.CreationDate, Ack = 'N'
I noted in the code what does not work (Everything after WHEN MATCHED) - no error just does not update when something is changed. If I remove the code after AND, then everything updates but every time the query is run - thus changing Ack to "N" when nothing really changed.
With some basic formatting the error became pretty obvious. You were missing a parenthesis in your predicates when matched. Notice how when this isn't a wall of sql you can actually see what is going on.
MERGE QA.dbo.SalesOrders AS TARGET USING
(
SELECT SOD.ORDNUM_28 + LINNUM_28 + DELNUM_28 AS [SalesOrd]
, SOD.PRTNUM_28
, PM.PMDES1_01
, SOD.CURDUE_28
, SOD.DUEQTY_28
, CPD.CUSTPRT_103
, SOM.CUSTPO_27
, CPD.UDFREF_103
, CPD.PRTNUM_103
, SOD.CreationDate
, CM.EMAIL1_23
, SOD.ORDNUM_28
FROM SO_Detail AS SOD
FULL OUTER JOIN Customer_Part_Data AS CPD ON SOD.PRTNUM_28 = CPD.PRTNUM_103
FULL OUTER JOIN SO_Master AS SOM ON SOD.ORDNUM_28 = SOM.ORDNUM_27
FULL OUTER JOIN Part_Master AS PM ON SOD.PRTNUM_28 = PM.PRTNUM_01
FULL OUTER JOIN Customer_Master AS CM ON SOD.CUSTID_28 = CUSTID_23
WHERE STATUS_28 = '3'
AND SOD.CreationDate > '09 / 14 / 2017' --Is this a date column? If so you need to use the ANSI standard YYYYmmdd
AND CUSTPO_27 <> ' '
AND SOM.STYPE_27 = 'CU'
AND SOD.STK_28 NOT LIKE '%RMA%'
AND SOD.STYPE_28 = 'CU'
) SOURCE
ON OrderNum = SOURCE.SalesOrd
WHEN MATCHED
AND
( --you need this here
PartNum <> SOURCE.PRTNUM_28
OR Description <> SOURCE.PMDES1_01
OR DueQty <> SOURCE.DUEQTY_28
OR CustPartNum <> SOURCE.CUSTPRT_103
OR CustPo <> SOURCE.CUSTPO_27
OR CustRev <> SOURCE.UDFREF_103
OR ShipDate <> SOURCE.CURDUE_28
OR email <> SOURCE.EMAIL1_23 --// This does not work
) --Without the parenthesis the update would fire when ANY of those conditions are met
THEN
UPDATE
SET PartNum = SOURCE.PRTNUM_28
, Description = SOURCE.PMDES1_01
, DueQty = SOURCE.DUEQTY_28
, CustPartNum = SOURCE.CUSTPRT_103
, CustPo = SOURCE.CUSTPO_27
, CustRev = SOURCE.UDFREF_103
, ShipDate = SOURCE.CURDUE_28
, email = SOURCE.EMAIL1_23
, OrgDate = SOURCE.CreationDate
, Ack = 'N'
Figured it out: My issue was, I am a victim of not understanding NULL. There is good discussion found here: Why does NULL = NULL evaluate to false in SQL server. Basically, the conditions could not fire the update because they simply did not know the answer (NULL). I needed to update my INSERT to include a CASE so if the value is NULL - insert ' ' (a Blank) so my conditions would have something to compare.

How to increase performance of this query?

I have an SQL query, it is running on MSSQL 2008 R2
View vMobileLastMobileHistory has about 1000 rows and
select * from vMobileLastMobileHistory is taking 0.2 sec
but this query is taking 5 seconds, how can I optimize this code?
(I think the problem is INTERSECT but I dont know how change this)
SELECT DISTINCT *
FROM
(
SELECT vMobileLastMobileHistory.*
FROM vMobileLastMobileHistory
LEFT OUTER JOIN MobileType_DomainAction ON
MobileType_DomainAction.tiMobileType = vMobileLastMobileHistory.tiMobileType
LEFT OUTER JOIN MobileType_User ON
MobileType_User.MobileID = MobileType_DomainAction.ID
WHERE MobileType_User.UserID = #UserID OR #UserID = - 1
INTERSECT
SELECT vMobileLastMobileHistory.*
FROM vMobileLastMobileHistory
LEFT OUTER JOIN dbo.Region_User ON
dbo.vMobileLastMobileHistory.strRegion = dbo.Region_User.strRegion
WHERE Region_User.iSystemUser = #UserID OR #UserID = - 1
INTERSECT
SELECT vMobileLastMobileHistory.*
FROM vMobileLastMobileHistory
LEFT OUTER JOIN Contractor_User ON
vMobileLastMobileHistory.strContractor = Contractor_User.strContractor
WHERE Contractor_User.iSystemUser = #UserID OR #UserID = - 1
)
The problem is that if you have any indexes on your iSytemUser columns, the optimise is unable to use them because it has to account for a specific userID being passed, or returning all results, it would be better to logically separate your two cases. In addition, since you don't care about any columns in the auxiliary tables, you could use EXISTS in your case of specific users to take advantage of a semi join:
IF (#UserID = -1)
BEGIN
SELECT DISTINCT *
FROM vMobileLastMobileHistory;
END
ELSE
BEGIN
SELECT DISTINCT *
FROM vMobileLastMobileHistory AS mh
WHERE EXISTS
( SELECT 1
FROM Contractor_User AS cu
WHERE cu.strContractor = mh.strContractor
AND cu.iSystemUser = #UserID
)
AND EXISTS
( SELECT 1
FROM Region_User AS ru
WHERE ru.strRegion = mh.strRegion
AND ru.iSystemUser = #UserID
)
AND EXISTS
( SELECT 1
FROM MobileType_DomainAction AS da
INNER JOIN MobileType_User AS mu
ON mu.MobileID = da.ID
WHERE da.tiMobileType = mh.tiMobileType
AND mu.iSystemUser = #UserID
);
END
Now you can have two execution plans for each case (returning all results, or for a specific user), in each case you only need to read from vMobileLastMobileHistory once, and you also limit the sorts required by removing the INTERSECT and replacing with 3 EXISTS clauses.
If they don't already exist then you may also which to consider some indexes on your tables. A good way of finding out what indexes would help is to run the query in SQL Server Management Studio with the option "Show Actual Execution Plan" enabled, this will then show you any missing indexes.
Most of time Intersect and Inner Join will be same. You are not share your data, so based on my knowledge and this link, I just replace intersect query into Inner join query as :
--I think you don't need distinct upper query. If you have issue inform me.
SELECT DISTINCT vml.*
FROM vMobileLastMobileHistory vml
LEFT OUTER JOIN MobileType_DomainAction mtda ON mtda.tiMobileType = vml.tiMobileType
LEFT OUTER JOIN MobileType_User ON MobileType_User.MobileID = mtda.ID
LEFT OUTER JOIN dbo.Region_User ON dbo.vml.strRegion = dbo.Region_User.strRegion
LEFT OUTER JOIN Contractor_User ON vml.strContractor = Contractor_User.strContractor
WHERE
(MobileType_User.UserID = #UserID
and Region_User.iSystemUser = #UserID or Contractor_User.iSystemUser = #UserID
) OR #UserID = - 1

Sub query in Store Procedure

I have a query in sql stored procedure. I want to get record from other query from its id how I do that.
SELECT t.Name ,t.CreatedDate ,t.CreatedBy , t.Amount
,t.Margin ,t.Probability ,t.Id
FROM (SELECT a = 1) a
CROSS JOIN
(SELECT
Name = HirschInternational_MSCRM.dbo.SalesOrderBase.Name
,CreatedDate=HirschInternational_MSCRM.dbo.SalesOrderBase.CreatedOn
,CreatedBy=HirschInternational_MSCRM.dbo.SystemUserBase.FullName
,Amount = totalamount
,Probability=CloseProbability
,Id=SalesOrderId
,Margin=(SELECT ( ISNULL( ((Sum(Price)-Sum(CurrentCost)) / NULLIF( Sum(Price), 0 ))*100, 0 ) )
FROM HirschInternational_MSCRM.dbo.ProductBase
JOIN HirschInternational_MSCRM.dbo.SalesOrderDetailBase
ON HirschInternational_MSCRM.dbo.SalesOrderDetailBase.ProductId = HirschInternational_MSCRM.dbo.ProductBase.ProductId
JOIN HirschInternational_MSCRM.dbo.SalesOrderBase
ON HirschInternational_MSCRM.dbo.SalesOrderBase.SalesOrderId = HirschInternational_MSCRM.dbo.SalesOrderDetailBase.SalesOrderId)
FROM HirschInternational_MSCRM.dbo.SalesOrderBase
JOIN HirschInternational_MSCRM.dbo.OpportunityBase
ON HirschInternational_MSCRM.dbo.SalesOrderBase.Opportunityid = HirschInternational_MSCRM.dbo.OpportunityBase.Opportunityid
JOIN HirschInternational_MSCRM.dbo.SystemUserBase
ON HirschInternational_MSCRM.dbo.SystemUserBase.SystemUserId = HirschInternational_MSCRM.dbo.SalesOrderBase.CreatedBy
WHERE YEAR(HirschInternational_MSCRM.dbo.SalesOrderBase.CreatedOn)=YEAR(GETDATE())
I want Margin from every record I want Output like
It's not entirely clear what you want, but you might be looking for something like
select *
from (your SQL SELECT statement goes here) t1
where id = ?;
I want to get margin of every record how I filter margin query for SalesOrderId
like
Margin=(SELECT ( ISNULL( ((Sum(Price)-Sum(CurrentCost)) / NULLIF( Sum(Price), 0 ))*100, 0 ) )
FROM HirschInternational_MSCRM.dbo.ProductBase
JOIN HirschInternational_MSCRM.dbo.SalesOrderDetailBase
ON HirschInternational_MSCRM.dbo.SalesOrderDetailBase.ProductId = HirschInternational_MSCRM.dbo.ProductBase.ProductId
JOIN HirschInternational_MSCRM.dbo.SalesOrderBase
ON HirschInternational_MSCRM.dbo.SalesOrderBase.SalesOrderId = HirschInternational_MSCRM.dbo.SalesOrderDetailBase.SalesOrderId
Where HirschInternational_MSCRM.dbo.SalesOrderBase.SalesOrderId= //SalesOrderId that I get in main query)
how I pass that SalesOrderId in this query

Does MS SQL Server Management Studio have a size limit associated with temp tables?

I am running a large query that uses a 710-row temp table of PIDs.
Something like :
insert into #AdelText values /* these are my PIDs*/
('0YyGRz5sYOFlDtmRArU9'),
('f9982cdb-dcd8-4aed-b534-566b65963a09'),
('4db7a20d-7b47-494f-9397-a0e5df6c059d')
-- 700 MORE
('4db7a20d-7b47-494f-9397-a0e6c059d')
Well then I have to run a query on it that is a pivot like so( note that the PID here corresponds to the temp-table PIDs):
select * from
(
select bis.SupplierID, bis.PID, rp.QuestionID,rp.Condition from respondentprofiles RP (nolock)
inner join BI_Sessions BIS (Nolock)
on bis.RespondentID = rp.RespondentID
inner join #adeltext at (nolock)
on bis.pid = at.pid
where
rp.QuestionID in
(
51, 48
)
and bis.surveyid = 14893
)
as sourcetable
PIVOT
(
MAX(condition)
for QuestionID in ([51],[48])
)
PivotedTable
I expect to get 710 rows back, but I am getting 360 rows back. this is very puzzling to me. any help is appreciated. thanks

Resources