SQL update using join impacting performance - sql-server

Please help me in tuning below mentioned update statement,
UPDATE t_cust
SET cust_name = td.cust_name,
cust_desc = td.cust_desc
FROM t_cust tc
JOIN t_data_cust td ON tc.cust_nr = td.cust_nr
AND tc.start_validity_date = ISNULL(#execution_date,td.start_validity_date)
AND (td.adj_id = #adj_id OR #adj_id IS NULL)
AND ( td.ln_status = '0')
WHERE td.cust_name <> tc.cust_name
OR td.cust_desc <> tc.cust_desc

Move the WHERE statement into the JOIN conditions.
Otherwise it should run well, if it still doesn't, please provide more information.

Related

Insert not working using MERGE in SQL server

I have a stored proc with the below query to insert/update using a MERGE in SQL Server but the query works fine for update, but its not working for Insert.
Although I gets correct updated records in Target but for new inserts, it fails.
Basically, i have 4 tables.SUPPORT_STAFF_BAK is the target table which needs to be updated from source table UNIQUE_DUP_TEST based on few conditions from other two tables(REF_FUNCTION,DATA_PERIOD) which i tried to fulfill using joins.
Based on the conditions, we need to check in target, if the same ggid exists for current data_period we need to update it else we need to insert new record again, based on the condition.
MERGE SUPPORT_STAFF_BAK AS SUPP_STAFF
USING
(SELECT G_UNIQUE.[GLOBAL_ID],
G_UNIQUE.[FIRST_NAME],
G_UNIQUE.[LAST_NAME],
G_UNIQUE.[EMAIL],
G_UNIQUE.[Gender],
G_UNIQUE.[DATE_OF_BIRTH],
G_UNIQUE.[PRODUCTION_UNIT_CODE],
ORG.[LEGAL_ENTITY_COUNTRY_CODE],
ORG.[LEGAL_ENTITY_COUNTRY],
G_UNIQUE.[JOB_NAME],
ORG.[BU_CODE],
ORG.[BU_NAME],
ORG.[SBU_CODE],
ORG.[SBU_NAME],
G_UNIQUE.[GRADE_LETTER],
CASE
WHEN G_UNIQUE.[EMPLOYEE_STATUS] = 'A' THEN 'Active'
WHEN G_UNIQUE.[EMPLOYEE_STATUS] = 'S' THEN 'Suspended'
WHEN G_UNIQUE.[EMPLOYEE_STATUS]= 'T' THEN 'Terminated'
END AS [EMPLOYEE_STATUS],
CASE WHEN G_UNIQUE.[CATEGORY] = 'DSS' THEN G_UNIQUE.[CATEGORY_DETAIL] ELSE ''
END AS [CATEGORY],
G_UNIQUE.[CATEGORY_DETAIL],
G_UNIQUE.[FIRST_JOINING_DATE],
PERIOD.DATA_PERIOD_ID
FROM UNIQUE_DUP_TEST G_UNIQUE
INNER JOIN GDH_ORG ORG
ON G_UNIQUE.PRODUCTION_UNIT_CODE=ORG.PRODUCTION_UNIT_CODE
INNER JOIN REF_FUNCTION FUNC
ON G_UNIQUE.CATEGORY_DETAIL=FUNC.FUNCTION_CODE
INNER JOIN DATA_PERIOD PERIOD
ON FUNC.FUNCTION_ID=PERIOD.FUNCTION_ID
WHERE PERIOD.DATA_YEAR=YEAR(GETDATE()) AND PERIOD.DATA_MONTH=MONTH(GETDATE())
) AS G_SOURCE
ON SUPP_STAFF.GGID = G_SOURCE.GLOBAL_ID AND SUPP_STAFF.PRODUCTION_UNIT_CODE=G_SOURCE.PRODUCTION_UNIT_CODE
AND SUPP_STAFF.DATA_PERIOD_ID=G_SOURCE.DATA_PERIOD_ID
WHEN MATCHED THEN
UPDATE SET
[SUPP_STAFF].[FIRST_NAME] = G_SOURCE.[FIRST_NAME],
[SUPP_STAFF].[LAST_NAME] = G_SOURCE.[LAST_NAME],
[SUPP_STAFF].[EMAIL] = G_SOURCE.[EMAIL],
[SUPP_STAFF].[GENDER] = G_SOURCE.[Gender],
[SUPP_STAFF].[DATE_OF_BIRTH] = G_SOURCE.[DATE_OF_BIRTH],
[SUPP_STAFF].[LEGAL_ENTITY_COUNTRY_CODE] = G_SOURCE.[LEGAL_ENTITY_COUNTRY_CODE],
[SUPP_STAFF].[LEGAL_ENTITY_COUNTRY_NAME] = G_SOURCE.[LEGAL_ENTITY_COUNTRY],
[SUPP_STAFF].[GCM_ROLE] = G_SOURCE.[JOB_NAME],
[SUPP_STAFF].[BU_CODE] = G_SOURCE.[BU_CODE],
[SUPP_STAFF].[BU_NAME] = G_SOURCE.[BU_NAME],
[SUPP_STAFF].[SBU_CODE] = G_SOURCE.[SBU_CODE],
[SUPP_STAFF].[SBU_NAME] = G_SOURCE.[SBU_NAME],
[SUPP_STAFF].[GRADE] = G_SOURCE.[GRADE_LETTER],
[SUPP_STAFF].[EMPLOYEE_STATUS] = G_SOURCE.[EMPLOYEE_STATUS],
[SUPP_STAFF].[EMPLOYEE_CATEGORY] = G_SOURCE.[CATEGORY],
[SUPP_STAFF].[START_DATE] = G_SOURCE.[FIRST_JOINING_DATE],
[SUPP_STAFF].[UPDATE_DATE] = GETDATE(),
[SUPP_STAFF].[UPDATE_USER] = CASE WHEN G_SOURCE.[EMPLOYEE_STATUS]='Terminated' THEN 'Delete'
WHEN G_SOURCE.[EMPLOYEE_STATUS]<>'Terminated' THEN 'Update'
END,
[SUPP_STAFF].[SUPPORT_STAFF_FUNCTION] = CASE WHEN G_SOURCE.[EMPLOYEE_STATUS]='Terminated' THEN NULL
WHEN G_SOURCE.[EMPLOYEE_STATUS]<>'Terminated' THEN G_SOURCE.[CATEGORY_DETAIL]
END
WHEN NOT MATCHED AND G_SOURCE.[CATEGORY] = 'CC1'
AND G_SOURCE.[EMPLOYEE_STATUS] IN ('A, S')
THEN
INSERT( [GGID],
[FIRST_NAME],
[LAST_NAME],
[EMAIL],
[GENDER],
[DATE_OF_BIRTH],
[LEGAL_ENTITY_COUNTRY_CODE],
[LEGAL_ENTITY_COUNTRY_NAME],
[GCM_ROLE],
[BU_CODE],
[BU_NAME],
[SBU_CODE],
[SBU_NAME],
[GRADE],
[EMPLOYEE_STATUS],
[EMPLOYEE_CATEGORY],
[START_DATE],
[UPDATE_DATE],
[UPDATE_USER],
[SUPPORT_STAFF_FUNCTION]
)
VALUES (
G_SOURCE.[GLOBAL_ID],
G_SOURCE.[FIRST_NAME],
G_SOURCE.[LAST_NAME],
G_SOURCE.[EMAIL],
G_SOURCE.[Gender],
G_SOURCE.[DATE_OF_BIRTH],
G_SOURCE.[LEGAL_ENTITY_COUNTRY_CODE],
G_SOURCE.[LEGAL_ENTITY_COUNTRY],
G_SOURCE.[JOB_NAME],
G_SOURCE.[BU_CODE],
G_SOURCE.[BU_NAME],
G_SOURCE.[SBU_CODE],
G_SOURCE.[SBU_NAME],
G_SOURCE.[GRADE_LETTER],
G_SOURCE.[EMPLOYEE_STATUS],
G_SOURCE.[CATEGORY_DETAIL],
G_SOURCE.[FIRST_JOINING_DATE],
GETDATE(),
'Insert',
G_SOURCE.[CATEGORY_DETAIL]
)
OUTPUT $action,
INSERTED.GGID AS GGID;
SELECT ##ROWCOUNT;
One of your assumptions is wrong. Either the source query has less rows than you think, or there is a match, or the insert condition is not met. Otherwise the query is OK.
To debug this I'd insert the source query into a temp table and manually inspect its contents to make sure they are what you expect.
You can then join to the target to see if your inserts maybe are converted to updates (e.g. select * from Source join Target on ...). Internally, a MERGE is just a full outer join anyway and you can reproduce that manually.
Right now nobody can tell you the exact answer. You need to debug this yourself and examine your data.
Finally I found the error. The error was at the below 2 places -
CASE WHEN G_UNIQUE.[CATEGORY] = 'DSS' THEN G_UNIQUE.[CATEGORY_DETAIL] ELSE '' END AS [CATEGORY],
I replaced it with
CASE WHEN G_UNIQUE.[CATEGORY] = 'DSS' THEN G_UNIQUE.[CATEGORY_DETAIL] ELSE ''
END AS [EMPLOYEE_FUNCTION],
Also I included one more column in my Source query which was missing-
G_UNIQUE.[CATEGORY],
Also, there below wrong code
WHEN NOT MATCHED AND G_SOURCE.[CATEGORY] = 'CC1'
AND G_SOURCE.[EMPLOYEE_STATUS] IN ('A, S')
was replaced by the below correct code-
WHEN NOT MATCHED AND G_SOURCE.[CATEGORY] = 'CC1'
AND G_SOURCE.[EMPLOYEE_STATUS] IN ('Active', 'Suspended')
Actually, I was missing 1 source column and was checking the value for the same while inserting and hence the insert was failing.
Also,in the source for Employee_status i checked the values as A,S and T and then replaced them with Active,Suspended,Terminated but while inserting in the When not matched , i was checking the value for A,S,T which every time was returning false and hence insert failed.

Converting T-SQL Left Join Subqueries to MS-Access

I need help in converting this T-SQL query to MS ACCESS. The error that I'm getting is JOIN expression not supported.
Update:
I can't add:
DDA ON TT.[Description] = DDA.AccountTypeDesc AND
H.AccountNumber = DDA.AccountNumber
But
DDA ON TT.[Description] = DDA.AccountTypeDesc
works. Is there a way to add the second condition?
T-SQL Query:
SELECT
*
FROM
(
SELECT
[PesoAmount] = CASE WHEN FE.IsoCode IS NULL THEN
LTRIM(STR(DFCF.CurrencyAmount, 20, 2))
ELSE
LTRIM(STR(DFCF.CurrencyAmount * FE.PhpConversionRate, 20, 2))
END,
DFCF.TransactionNumber,
DFCF.AccountNumber,
DFCF.CountryCd,
DFCF.TransactionTypeCd,
DFCF.Time,
DFCF.Date,
DFCF.TransactionStatusCd,
DFCF.TransactionCurrencyCd,
DFCF.BranchNumber,
DFCF.RemitterExtPartyCd,
DFCF.BeneficiaryExtPartyCd,
DFCF.PostedDate,
DFCF.AssociateNumber,
DFCF.ExecutingPartyNumber,
DFCF.CurrencyAmount,
DFCF.CurrencyAmountInTxnCcy,
DFCF.CurrencyAmountInAccountCcy,
DFCF.SecondaryAccountKey,
DFCF.RelatedInd,
DFCF.ThirdPartyInd,
DFCF.TransactionDescription,
DFCF.SecurityName,
DFCF.DealNumber
FROM
dbo.DesFactCashFlow DFCF (NOLOCK) LEFT JOIN
dbo.ForeignExchange FE (NOLOCK) ON DFCF.TransactionCurrencyCd = FE.IsoCode
)
H LEFT JOIN
dbo.Ctr C (NOLOCK) ON H.PesoAmount = C.PesoAmountFaceValueSumInsured AND
H.AccountNumber = C.AccountNumber AND
H.TransactionTypeCd = C.TransactionType LEFT JOIN
dbo.TransactionType TT (NOLOCK) ON H.TransactionTypeCd = TT.Code LEFT JOIN
(
SELECT
[AccountNumber] = DDA2.AccountNumber,
[AccountTypeDesc] = DDA2.AccountTypeDesc,
[LineOfBusinessName] = MAX(DDA2.LineOfBusinessName),
[AccountCurrencyCode] = MAX(DDA2.AccountCurrencyCode),
[AccountCurrencyName] = MAX(DDA2.AccountCurrencyName),
[AccountRegistrationTypeDesc] = MAX(DDA2.AccountRegistrationTypeDesc),
[AccountRegistrationName] = MAX(DDA2.AccountRegistrationName),
[AccountName] = MAX(DDA2.AccountName),
[AlternateName] = MAX(DDA2.AlternateName),
[AccountOpenDate] = MAX(DDA2.AccountOpenDate),
[AccountCloseDate] = MAX(DDA2.AccountCloseDate),
[AccountStatusDesc] = MAX(DDA2.AccountStatusDesc),
[DormantInd] = MAX(DDA2.DormantInd),
[ProductLineName] = MAX(DDA2.ProductLineName),
[ProductCategoryName] = MAX(DDA2.ProductCategoryName),
[ProductTypeName] = MAX(DDA2.ProductTypeName),
[ProductName] = MAX(DDA2.ProductName),
[ProductNumber] = MAX(DDA2.ProductNumber),
[AccountTaxId] = MAX(DDA2.AccountTaxId),
[AccountTaxIdTypeCode] = MAX(DDA2.AccountTaxIdTypeCode),
[AccountTaxStateCode] = MAX(DDA2.AccountTaxStateCode),
[AccountPrimaryBranchName] = MAX(DDA2.AccountPrimaryBranchName),
[MailingAddress1] = MAX(DDA2.MailingAddress1),
[MailingAddress2] = MAX(DDA2.MailingAddress2),
[MailingCityName] = MAX(DDA2.MailingCityName),
[MailingStateCode] = MAX(DDA2.MailingStateCode),
[MailingStateName] = MAX(DDA2.MailingStateName),
[MailingPostalCode] = MAX(DDA2.MailingPostalCode),
[MailingCountryCode] = MAX(DDA2.MailingCountryCode),
[MailingCountryName] = MAX(DDA2.MailingCountryName),
[CurrencyBasedAccountInd] = MAX(DDA2.CurrencyBasedAccountInd),
[MaturityDate] = MAX(DDA2.MaturityDate),
[OriginalLoanAmount] = MAX(DDA2.OriginalLoanAmount),
[CollateralTypeDesc] = MAX(DDA2.CollateralTypeDesc),
[CollateralTypeCode] = MAX(DDA2.CollateralTypeCode),
[InsuredAmount] = MAX(DDA2.InsuredAmount),
[EmployeeInd] = MAX(DDA2.EmployeeInd)
FROM
dbo.DesDimAccount DDA2 (NOLOCK)
GROUP BY
DDA2.AccountNumber,
DDA2.AccountTypeDesc
)
DDA ON RTRIM(TT.[Description]) = RTRIM(DDA.AccountTypeDesc) AND
H.AccountNumber = DDA.AccountNumber
EDIT: I replaced the query with the AS keyword. I get the same error.
MS Access Query with Error:
SELECT
'H' AS [HeaderRecordIndicator],
'1' AS [SupervisingAgency],
'0' + I.InstitutionCode AS [InstitutionCode],
CONVERT(char(8), H.Date, 112) AS [ReportDate],
'CTR' AS [ReportType],
'21' AS [FormatCode],
'1' AS [SubmissionType]
FROM
(((
SELECT
IIF(ISNULL(FE.IsoCode), FORMAT(DFCF.CurrencyAmount, "##################.00"), FORMAT(DFCF.CurrencyAmount * FE.PhpConversionRate, "##################.00")) AS [PesoAmount],
DFCF.TransactionNumber,
DFCF.AccountNumber,
DFCF.CountryCd,
DFCF.TransactionTypeCd,
DFCF.Time,
DFCF.Date,
DFCF.TransactionStatusCd,
DFCF.TransactionCurrencyCd,
DFCF.BranchNumber,
DFCF.RemitterExtPartyCd,
DFCF.BeneficiaryExtPartyCd,
DFCF.PostedDate,
DFCF.AssociateNumber,
DFCF.ExecutingPartyNumber,
DFCF.CurrencyAmount,
DFCF.CurrencyAmountInTxnCcy,
DFCF.CurrencyAmountInAccountCcy,
DFCF.SecondaryAccountKey,
DFCF.RelatedInd,
DFCF.ThirdPartyInd,
DFCF.TransactionDescription,
DFCF.SecurityName,
DFCF.DealNumber
FROM
DesFactCashFlow DFCF LEFT JOIN
ForeignExchange FE ON DFCF.TransactionCurrencyCd = FE.IsoCode
) AS
H LEFT JOIN
Ctr C ON H.PesoAmount = C.PesoAmountFaceValueSumInsured AND
H.AccountNumber = C.AccountNumber AND
H.TransactionTypeCd = C.TransactionType) LEFT JOIN
TransactionType TT ON H.TransactionTypeCd = TT.Code) LEFT JOIN
(
SELECT
DDA2.AccountNumber AS [AccountNumber],
DDA2.AccountTypeDesc AS [AccountTypeDesc],
MAX(DDA2.LineOfBusinessName) AS [LineOfBusinessName],
MAX(DDA2.AccountCurrencyCode) AS [AccountCurrencyCode],
MAX(DDA2.AccountCurrencyName) AS [AccountCurrencyName],
MAX(DDA2.AccountRegistrationTypeDesc) AS [AccountRegistrationTypeDesc],
MAX(DDA2.AccountRegistrationName) AS [AccountRegistrationName],
MAX(DDA2.AccountName) AS [AccountName],
MAX(DDA2.AlternateName) AS [AlternateName],
MAX(DDA2.AccountOpenDate) AS [AccountOpenDate],
MAX(DDA2.AccountCloseDate) AS [AccountCloseDate],
MAX(DDA2.AccountStatusDesc) AS [AccountStatusDesc],
MAX(DDA2.DormantInd) AS [DormantInd],
MAX(DDA2.ProductLineName) AS [ProductLineName],
MAX(DDA2.ProductCategoryName) AS [ProductCategoryName],
MAX(DDA2.ProductTypeName) AS [ProductTypeName],
MAX(DDA2.ProductName) AS [ProductName],
MAX(DDA2.ProductNumber) AS [ProductNumber],
MAX(DDA2.AccountTaxId) AS [AccountTaxId],
MAX(DDA2.AccountTaxIdTypeCode) AS [AccountTaxIdTypeCode],
MAX(DDA2.AccountTaxStateCode) AS [AccountTaxStateCode],
MAX(DDA2.AccountPrimaryBranchName) AS [AccountPrimaryBranchName],
MAX(DDA2.MailingAddress1) AS [MailingAddress1],
MAX(DDA2.MailingAddress2) AS [MailingAddress2],
MAX(DDA2.MailingCityName) AS [MailingCityName],
MAX(DDA2.MailingStateCode) AS [MailingStateCode],
MAX(DDA2.MailingStateName) AS [MailingStateName],
MAX(DDA2.MailingPostalCode) AS [MailingPostalCode],
MAX(DDA2.MailingCountryCode) AS [MailingCountryCode],
MAX(DDA2.MailingCountryName) AS [MailingCountryName],
MAX(DDA2.CurrencyBasedAccountInd) AS [CurrencyBasedAccountInd],
MAX(DDA2.MaturityDate) AS [MaturityDate],
MAX(DDA2.OriginalLoanAmount) AS [OriginalLoanAmount],
MAX(DDA2.CollateralTypeDesc) AS [CollateralTypeDesc],
MAX(DDA2.CollateralTypeCode) AS [CollateralTypeCode],
MAX(DDA2.InsuredAmount) AS [InsuredAmount],
MAX(DDA2.EmployeeInd) AS [EmployeeInd]
FROM
DesDimAccount DDA2
GROUP BY
DDA2.AccountNumber,
DDA2.AccountTypeDesc
) AS
DDA ON RTRIM(TT.[Description]) = RTRIM(DDA.AccountTypeDesc) AND
H.AccountNumber = DDA.AccountNumber
Here is the simplified query with the same error:
SELECT
*
FROM
(((
SELECT
IIF(ISNULL(FE.IsoCode), FORMAT(DFCF.CurrencyAmount, "##################.00"), FORMAT(DFCF.CurrencyAmount * FE.PhpConversionRate, "##################.00")) AS [PesoAmount],
DFCF.TransactionNumber,
DFCF.TransactionCurrencyCd,
FROM
DesFactCashFlow DFCF LEFT JOIN
ForeignExchange FE ON DFCF.TransactionCurrencyCd = FE.IsoCode
) AS
H LEFT JOIN
Ctr C ON H.PesoAmount = C.PesoAmountFaceValueSumInsured AND
H.AccountNumber = C.AccountNumber AND
H.TransactionTypeCd = C.TransactionType) LEFT JOIN
TransactionType TT ON H.TransactionTypeCd = TT.Code) LEFT JOIN
(
SELECT
DDA2.AccountNumber AS [AccountNumber],
DDA2.AccountTypeDesc AS [AccountTypeDesc],
MAX(DDA2.LineOfBusinessName) AS [LineOfBusinessName],
FROM
DesDimAccount DDA2
GROUP BY
DDA2.AccountNumber,
DDA2.AccountTypeDesc
) AS
DDA ON RTRIM(TT.[Description]) = RTRIM(DDA.AccountTypeDesc) AND
H.AccountNumber = DDA.AccountNumber
Give up trying to convert the SQL text from your T-SQL query to Access SQL. Create a new Access query from scratch and use the T-SQL query only as a road map. Add your data sources and set up the joins. The query designer will guarantee you create the joins in the manner which keeps the db engine happy: addition and positioning of parentheses it requires for queries with more than one join; the rules which apply for LEFT JOINs; and so forth. Just let the designer handle those details for you.
The designer will choke in Design View due to the functions in this part of your last join:
RTRIM(TT.[Description]) = RTRIM(DDA.AccountTypeDesc)
So leave out the RTRIM() functions while you're setting up the joins in Design View. Don't worry that the query doesn't return the correct results. After you get joins which satisfy the db engine, switch to SQL View and add the RTRIM() functions back in.
After you get the joins set up correctly, then add in your field expressions to the SELECT list.
Also you may find it easier to manage your complex query by breaking out the subqueries as separate saved queries --- then reference those queries by name in the master query just as you would table sources.
The problem is with the penultimate line:
DDA ON RTRIM(TT.[Description]) = RTRIM(DDA.AccountTypeDesc) AND
The Design View of the Access query designer can't work with functions in the ON part of the clause. You must remove the RTRIM.
Access is parenthesis happy. Wrap each join expression in parentheses, the ON clauses themselves, and each pair of tables.
You can't use CONVERT, NOLOCK, or CASE.
Which version of MSAccess you are using in your system? I just tried in 2007 version and RTRIM is working.

Translating a QueryExpression into SQL: what's a Natural join?

I am trying to translate a QueryExpression that is in some existing code into a T-SQL select statement.
I've run across the following statement and I'm having trouble understanding what they mean by a Natural Join:
linkEntity1.JoinOperator = JoinOperator.Natural;
Would this be equivalent to an Inner Join in T-SQL? Googling has not been much help.
Here's the rest of the QueryExpression Code:
QueryExpression query = new QueryExpression();
query.EntityName = "showinfo";
ColumnSet columns = new ColumnSet();
columns.Attributes = new String[] { "company" };
query.ColumnSet = columns;
query.Criteria = new FilterExpression();
query.Criteria.FilterOperator = LogicalOperator.And;
ConditionExpression condition1 = new ConditionExpression();
condition1.AttributeName = "company";
condition1.Operator = ConditionOperator.NotNull;
query.Criteria.Conditions = new ConditionExpression[] { condition1 };
LinkEntity linkEntity1 = new LinkEntity();
linkEntity1.JoinOperator = JoinOperator.Natural;
linkEntity1.LinkFromEntityName = "show";
linkEntity1.LinkFromAttributeName = "showid";
linkEntity1.LinkToEntityName = "showintegration";
linkEntity1.LinkToAttributeName = "showcode";
linkEntity1.LinkCriteria = new FilterExpression();
linkEntity1.LinkCriteria.FilterOperator = LogicalOperator.And;
ConditionExpression condition2 = new ConditionExpression();
condition2.AttributeName = "showend";
condition2.Operator = ConditionOperator.Null;
linkEntity1.LinkCriteria.Conditions = new ConditionExpression[] { condition2 };
query.LinkEntities = new LinkEntity[] { linkEntity1 };
There is no equivalent in SQL Server of a natural join where table intersect is based on column names by the RDBMS.
I'm glad of that because it is at best ambiguous and at worst dangerous. JOINs should be explicit. Examples why:
having a InsertedBy column in both tables (quite common): should we have to prefix with the table name to remove ambiguity?
future DDL that add columns that change JOIN semantics
See
Natural join in SQL Server
SQL Server - lack of NATURAL JOIN / x JOIN y USING(field)
Edit:
It looks like natural join means "don't repeat the column in the output" (like USING in MySQL would do) according to the JoinOperator Enumeration.
If I understand this (debatable!) it's misleading. Especially when I read the "LeftOuter" narrative..
A natural join compares all columns in the two tables that have the same column names. It's equivalent to an inner join with the matching columns explicitly listed.
Yes - the natural join is inner join - so you can write:
select * from tab1, tab2 where tab1.col1 = tab2.col1
as
select * from tab1 inner join tab2 on tab1.col1 = tab2.col1

What is the problem with the logic in my UPDATE statement?

I would appreciate some help with an UPDATE statement.
I want to update tblOrderHead with the content from tblCustomer where the intDocumentNo corresponds to the parameter #intDocumentNo. But when I run the my statement, the order table is only updated with the content from the first row of the customer table.
What is the problem with my logic?
I use Microsoft SQL Server.
Thanks,
Stefan
UPDATE dbo.tblOrderHead
SET dbo.tblOrderHead.intCustomerNo = #intCustomerNo ,
dbo.tblOrderHead.intPaymentCode = dbo.tblCustomer.intPaymentCode,
dbo.tblOrderHead.txtDeliveryCode = dbo.tblCustomer.txtDeliveryCode,
dbo.tblOrderHead.txtRegionCode = dbo.tblCustomer.txtRegionCode,
dbo.tblOrderHead.txtCurrencyCode = dbo.tblCustomer.txtCurrencyCode,
dbo.tblOrderHead.txtLanguageCode = dbo.tblCustomer.txtLanguageCode
FROM dbo.tblOrderHead
INNER JOIN dbo.tblCustomer ON dbo.tblOrderHead.intOrderNo = #intDocumentNo
Solution
If anyone as stupid as me out there thing the same thing, this is how you solve it:
UPDATE dbo.tblOrderHead
SET dbo.tblOrderHead.intCustomerNo = #intCustomerNo ,
dbo.tblOrderHead.intPaymentCode = dbo.tblCustomer.intPaymentCode,
dbo.tblOrderHead.txtDeliveryCode = dbo.tblCustomer.txtDeliveryCode,
dbo.tblOrderHead.txtRegionCode = dbo.tblCustomer.txtRegionCode,
dbo.tblOrderHead.txtCurrencyCode = dbo.tblCustomer.txtCurrencyCode,
dbo.tblOrderHead.txtLanguageCode = dbo.tblCustomer.txtLanguageCode
FROM dbo.tblOrderHead
INNER JOIN dbo.tblCustomer ON dbo.tblOrderHead.intCustomerNo = dbo.tblCustomer.intCustomerNo
AND dbo.tblOrderHead.intOrderNo = #intDocumentNo
Problem is that, you are not specifying the condition on which the 2 tables tblOrderHead, tblCustomer need to be joined!
you need something like
INNER JOIN dbo.tblCustomer
ON dbo.tblOrderHead.someColumn = dbo.tblCustomer.someColumn
and dbo.tblOrderHead.intOrderNo = #intDocumentNo

Update field from another table

Is there a better way to write the following simple SQL Server 2005 update statement? This just seems a bit messy inefficient.
UPDATE QuotationItem
SET Recurring_Cost =
(SELECT TOP (1) Recurring_Cost
FROM Products
WHERE (Remote_ID = QuotationItem.Product_ID))
WHERE (Quotation_ID = 115)
Thanks,
Nick
How About using a join
UPDATE QuotationItem
SET Recurring_Cost = p.recurring_cost
FROM QuotationItem q join Products p on q.Product_ID = p.Remote_ID
WHERE q.Quotation_ID = 115
Is your TOP 1 really needed? If it is, since you don't specify an ordering, you've got pretty random results from your query anyway! If it is not really necessary, this will do:
UPDATE q
SET Recurring_Cost = p.RecurringCost
FROM QuotationItem q
INNER JOIN
Products p
ON p.Remote_ID = q.Product_ID
WHERE q.Quotation_ID = 115

Resources