I am writing a sql query to pull some data from one of our linked oracle servers.
The only problem with this query is with the two date add rows (with them removed the query runs) but i need their data.
I receive the below error:
OLE DB provider "MSDAORA" for linked server "MAGINUS" returned message "ORA-00904: "DATEADD": invalid identifier
Could anyone prescribe a syntax for these?
Thanks in advance
Will
DECLARE #TSQL VARCHAR(8000)
,#CUSTOMER_ACCOUNT VARCHAR(20)
SELECT #TSQL1 = '
SELECT * FROM OPENQUERY(MAGINUS,''
SELECT
CM.CUSTOMER_ACCOUNT AS "CustomerAccount"
,CM.CONTACT_NAME AS "ContactName"
,CM.MEMBERSHIP_NUMBER AS "MembershipNumber"
,P.LONG_DESCRIPTION_1 AS "ProductDescription"
,DATEADD(SECOND, CM.MEMBERSHIP_START_DATE, "19700101") AS "MembershipStartDate"
,DATEADD(SECOND, CM.MEMBERSHIP_EXPIRY_DATE, "19700101") AS "MemberhrshipEndDate"
,SH.ORDER_VALUE AS "Price Paid"
FROM MAGINUS.CUSTOMER_MEMBERSHIP CM
INNER JOIN MAGINUS.PRODUCT P
ON CM.PRODUCT_CODE = P.PRODUCT_CODE
INNER JOIN MAGINUS.SALES_HEADER SH
ON CM.CUSTOMER_ACCOUNT = SH.CUSTOMER_ACCOUNT
AND CM.SALES_DOCUMENT_NUM = SH.SALES_DOCUMENT_NUM
WHERE CM.CUSTOMER_ACCOUNT = ''''' + #CUSTOMER_ACCOUNT + ''''''')'
EXEC (#TSQL1)
Dateadd is valid for SQL Server, but the query you send to the Oracle db needs to be valid for oracle. So you need to move the dateadd outside of the openquery, and into the SQL Server bit:
DECLARE #TSQL VARCHAR(8000)
,#CUSTOMER_ACCOUNT VARCHAR(20)
SELECT #TSQL1 = '
SELECT CustomerAccount
,ContactName
,MembershipNumber
,ProductDescription
,DATEADD(SECOND, MembershipStartDate, ''19700101'') AS MembershipStartDate
,DATEADD(SECOND, MemberhrshipEndDate, ''19700101'') AS MemberhrshipEndDate
,Price Paid
FROM OPENQUERY(MAGINUS,''
SELECT
CM.CUSTOMER_ACCOUNT AS "CustomerAccount"
,CM.CONTACT_NAME AS "ContactName"
,CM.MEMBERSHIP_NUMBER AS "MembershipNumber"
,P.LONG_DESCRIPTION_1 AS "ProductDescription"
,CM.MEMBERSHIP_START_DATE AS "MembershipStartDate"
,CM.MEMBERSHIP_EXPIRY_DATE AS "MemberhrshipEndDate"
,SH.ORDER_VALUE AS "Price Paid"
FROM MAGINUS.CUSTOMER_MEMBERSHIP CM
INNER JOIN MAGINUS.PRODUCT P
ON CM.PRODUCT_CODE = P.PRODUCT_CODE
INNER JOIN MAGINUS.SALES_HEADER SH
ON CM.CUSTOMER_ACCOUNT = SH.CUSTOMER_ACCOUNT
AND CM.SALES_DOCUMENT_NUM = SH.SALES_DOCUMENT_NUM
WHERE CM.CUSTOMER_ACCOUNT = ''''' + #CUSTOMER_ACCOUNT + ''''''')'
EXEC (#TSQL1)
Related
I have a query that behaves differently depending on the client executing it.
I got instantaneous result (163 rows) with Azure Data Studio.
More than 7 minutes for SQL Management Studio, Report Builder, SSRS Web Portal.
What is even better is that I achieve the same performance in SSMS if I remove two columns from the select OR if I add 2 null columns.
SELECT
mycols,
(...),
null,
null
FROM
(...)
The explain plan is the same, I can't understand a thing. Tuning advisor has no advice.
I thought it has something to do why the client options and the only one that was different was the ARITHMETIC_ABORT_ENABLED that was FALSE. After setting it to true in SSMS still no effect.
I use SQL Server 2019.
Here is the query:
DECLARE #UserID as VARCHAR(30) = CURRENT_USER
DECLARE #ProductionCenterSwipCode as VARCHAR(30) = 'AIX'
DECLARE #ResourceName as VARCHAR(30) = NULL
DECLARE #ActivityCode as VARCHAR(30) = '{ALL}'
DECLARE #SubactivityCode as VARCHAR(30) = '{ALL}'
DECLARE #WorkNatureCode as VARCHAR(30) = '{ALL}'
DECLARE #ClientId as INT = -9999
DECLARE #ContractId as INT = -9999
DECLARE #StartDate as DATE= CAST( '2021-04-01' AS DATE)
DECLARE #EndDate as DATE = CAST( '2021-05-30' AS DATE)
SELECT concat(cct.cct_activity_domain_code, ' - ', cct.cct_activity_domain_label) domain_of_activity,
concat(hrh.hrh_production_center_swip_code, ' - ', hrh.hrh_production_center_name) resource_production_center,
hrh.hrh_full_name resource,
dat.dat_date Date_logged,
tim.tim_number_hours_logged time_logged,
concat(rng.rng_type_of_work_code, ' - ', rng.rng_type_of_work_label) type_of_work,
tsk.tsk_code task,
concat(sta.wat_activity_code , ' - ', sta.wat_activity_label) activity,
cct.cct_client_reference client_contract,
cli.cli_name client_name,
wko.wko_swip_id wo_id,
wko.wko_client_reference wo_client_reference,
concat(sta.wat_workorder_type_code, ' - ', sta.wat_workorder_type_label) wo_type,
wko.wko_current_status_label wo_status,
rng.rng_label range_element,
rnh.rnh_current_status_label range_element_status,
concat(sta.wat_subactivity_code, ' - ', sta.wat_subactivity_label) sub_activity,
concat(sta.wat_nature_of_work_code, ' - ', sta.wat_nature_of_work_label) work_nature,
concat(sta.wat_priority_code, ' - ', sta.wat_priority_label) priority,
concat(sta.wat_complexity_code, ' - ', sta.wat_complexity_label) complexity,
concat(sta.wat_skill_level_code, ' - ', sta.wat_skill_level_label) skill_level,
concat(sta.wat_program_code, ' - ', sta.wat_program_label) program,
concat(sta.wat_perimeter_code, ' - ', sta.wat_perimeter_label) technical_scope,
concat(sta.wat_customer_production_center_code, ' - ', sta.wat_customer_production_center_label) client_production_center,
concat(sta.wat_scenario_code, ' - ', sta.wat_scenario_label) production_scenario,
concat(sta.wat_application_classification_code, ' - ', sta.wat_application_classification_label) application_ranking,
concat(sta.wat_customer_technical_leader_code, ' - ', sta.wat_customer_technical_leader_label) client_technical_leader,
wko.wko_current_start_date wo_start_date,
wko.wko_current_commit_end_date wo_end_date_commitment,
wko.wko_last_delivery_date wo_last_delivery_date,
wko.wko_highest_id highest_level_wo_id,
wko.wko_highest_client_reference highest_level_wo_client_refence,
wko.wko_batch_reference wo_batch_reference,
wko.wko_label wo_descriprion
FROM dwh_swip.swip.f_logged_time tim
INNER JOIN dwh_swip.swip.d_human_resource_hstr hrh ON hrh.hrh_id = tim.tim_hrh_id
INNER JOIN dwh_swip.swip.d_range_element rng ON rng.rng_id = tim.tim_rng_id
INNER JOIN dwh_swip.swip.d_date dat ON dat.dat_id = tim.tim_dat_id
INNER JOIN dwh_swip.swip.d_range_element_hstr rnh ON rnh.rnh_id = tim.tim_rnh_id
INNER JOIN dwh_swip.swip.d_task tsk ON tsk.tsk_id = tim.tim_tsk_id
INNER JOIN dwh_swip.swip.d_workorder wko ON wko.wko_id = tim.tim_wko_id
INNER JOIN dwh_swip.swip.d_client_contract cct ON cct.cct_id = tim.tim_cct_id
INNER JOIN dwh_swip.swip.d_client cli ON cli.cli_id = tim.tim_cli_id
INNER JOIN dwh_swip.swip.d_wo_structuring_attributes sta ON sta.wat_id = tim.tim_wat_id
WHERE exists ( SELECT 1
FROM swip.b_user_perimeter
WHERE upr_domain_id = (#UserID) AND upr_active_domain_code = cct.cct_activity_domain_code )
AND hrh.hrh_production_center_swip_code IN (#ProductionCenterSwipCode)
AND cct.cct_activity_domain_code IN (N'ADS_TD',N'ADS_VV_ILL',N'AC_TD',N'BI',N'DEF_TD',N'DOM_MG',N'HE_TD',N'INDUSTRY',N'LLA DOM',N'NAV_CU_SUP',N'NAV_ENG',N'NAV_TD',N'non applicable',N'llaxx',N'unknown')
AND (#ResourceName IS NULL or #ResourceName IS NOT NULL AND hrh.hrh_full_name like N'%'+ #ResourceName + N'%')
AND ('{ALL}' in (#ActivityCode) or '{ALL}' NOT IN (#ActivityCode) AND sta.wat_activity_code IN (#ActivityCode))
AND ('{ALL}' in (#SubactivityCode) or '{ALL}' NOT IN (#SubactivityCode) AND sta.wat_subactivity_code IN (#SubactivityCode))
AND ('{ALL}' in (#WorkNatureCode) or '{ALL}' NOT IN (#WorkNatureCode) AND sta.wat_nature_of_work_code IN (#WorkNatureCode))
AND (-9999 in (#ClientId) or -9999 NOT IN (#ClientId) AND tim.tim_cli_id IN (#ClientId))
AND (-9999 in (#ContractId) or -9999 NOT IN (#ContractId) AND tim.tim_cct_id IN (#ContractId))
AND tim.tim_dat_id >= (YEAR(#StartDate)*10000 + MONTH(#StartDate)*100 + DAY(#StartDate))
AND tim.tim_dat_id <= (YEAR(#EndDate)*10000 + MONTH(#EndDate)*100 + DAY(#EndDate) )
It was an SQL Server bug. Answer from Microsoft support:
ISSUE: You were having performance issues with a specific query. On
SSMS and SSRS, it was taking longer to finish. On Azure Data Studio
and SQL CMD, it was running faster
Fixes a performance issue when a query outputs NULL values following a semi join in SQL Server 2019 for a database with UTF8.
To solve the issue, you have to apply the latest CU on SQL, which is the CU11
At first Microsoft had trouble figuring it out because they didn't know at that time that the behaviour would change depending on the SQL client.
Now they know ^^
I have a query that joins multiple Data Sources together, I need a query that will select from a variable amount of tables depending on the date range I send it.
Joining Query
SELECT I.SerialNumber as DataSource,Deployed,Removed
FROM InstrumentDeployments ID
INNER JOIN Instruments I On I.Id = ID.InstrumentId
INNER JOIN Points P On P.Id = ID.PointId
WHERE P.Id = 1
ORDER BY Deployed
Joining Query Result
So from the above query result, if I wanted to select all of the historical information, it would go through and get the data from the specific tables
(called DataSource in query above) dependant on the relevant date.
Final Query - Something like this but the variable tables from query result above.
SELECT * FROM (VariableTables) WHERE DateRange BETWEEN '2016-09-07' and '2018-07-28'
Thanks
Please note that this is completely untested as the sample data is an image (and I can't copy and paste text from an image). If this doesn't work, please provide your sample data as text.
Anyway, the only way you'll be able to achieve this is with Dynamic SQL. This also, like in the comments, assumes that every table has the exact same definition. if it doesn't you'll likely get a failure (perhaps a conversion error, or that for a UNION query all tables must have the same number of columns). If they don't, you'll need to explicitly define your columns.
Again, this is untested, however:
DECLARE #SQL nvarchar(MAX);
SET #SQL = STUFF((SELECT NCHAR(10) + N'UNION ALL' + NCHAR(10) +
N'SELECT *' + NCHAR(10) +
N'FROM ' + QUOTENAME(I.SerialNumber) + NCHAR(10) +
N'WHERE DateRange BETWEEN #dStart AND #dEnd'
FROM InstrumentDeployments ID
INNER JOIN Instruments I ON I.Id = ID.InstrumentId
INNER JOIN Points P ON P.Id = ID.PointId
WHERE P.Id = 1
ORDER BY Deployed
FOR XML PATH(N'')),1,11,N'') + N';';
PRINT #SQL; --Your best friend.
DECLARE #Start date, #End date;
SET #Start = '20160907';
SET #End = '20180728';
EXEC sp_executesql #SQL, N'#dStart date, #dEnd date', #dStart = #Start, #dEnd = #End;
This question already has answers here:
Dynamic SQL Not Converting VARCHAR To INT (shouldn't anyway)
(2 answers)
Closed 4 years ago.
I have a dynamic SQL query inside a stored procedure that works and gives me the correct results. But it is taking too long-because I have to compare as varchar instead of int. I believe #query variable in SQL server requires the statement to be a unicode.
Here is the dynamic sql part
ALTER PROCEDURE [dbo].[sp_GetRows]( #Id varchar(64))
AS
BEGIN
DECLARE #Query nvarchar(4000),
#Comp varchar(256)
SELECT #Comp
= STUFF((
SELECT DISTINCT ',' + char(39)+
tci.Component +char(39)
FROM TCI tci WITH(NOLOCK)
JOIN CDetail cd WITH(NOLOCK)
ON tci.ParentCId = cd.CIdentifier
WHERE tci.ParentCId = #Id
AND cd.ParentBranch IS NULL
FOR XML PATH('')),1,1,'')
SET #Query
= 'WITH CTE AS
(
SELECT '+#Id+' as ParentCId, CIdentifier as ChildCId,
a.Comp as Comp
from dbo.CD cd WITH(NOLOCK)
INNER JOIN
(SELECT DISTINCT ChildCId,Comp
FROM TCI tc WITH(NOLOCK)
WHERE ParentCId = '+ #Id + '
) a
ON cd.CIdentifier= a.ChildCId
);
EXEC (#Query)
END;
Here is the comparison-
SELECT CIdentifier FROM #tempTable temp WITH(NOLOCK)
WHERE temp.CIdentifier < '+#Id+'....
This compares as CIdentifier =1122233 instead of CIdentifier ='1122233' because dynamic SQL is not allowing me to pass it as an int. I keep getting the 'cannot convert varchar to int error'
So I used parameterized query - hoping that would enable me to pass int values.Here is the query part
SET #Query
= N';WITH CTE AS
(
......
(SELECT DISTINCT ChildCId,Comp
FROM TCI tc WITH(NOLOCK)
WHERE ParentCId = #Id
AND ChildCId + tc.Comp
NOT IN
(SELECT ChildId + Comp FROM dbo.TCI WITH(NOLOCK)
WHERE ParentId IN (SELECT CIdentifier FROM #tempTable WITH(NOLOCK)
WHERE temp.CIdentifier < #Idn
AND Comp IN ( #Comp))
)
)
)a
ON cd.CIdentifier= a.ChildId
)
SELECT * FROM CTE;'
EXEC sp_executeSQL #Query,'#Id VARCHAR(64),#Idn INT,#comp VARCHAR(256)',#Id=#Id,#Idn=#Idn,#comp =#comp
This gives me incorrect results and when I saw the execution using a trace - saw that values are not being passed onto the query. How can I get the query to pick up the variables?
Just change WHERE ParentCId = '+ #Id + ' to WHERE ParentCId = '+ cast(#Id as varchar(16)) + ' in the first query. The problem is SQL Server see's + as addition when the value is a numeric type, or date, and concatenation when it isn't. This is where you get the error from. However, when you do this, it will not make SQL Server compare it as a string literal so you don't have to worry about that. You can see this if you use PRINT (#Query) at the end instead of EXEC (#Query)
Note, this needs to be changed at the other locations you have any NUMERIC data type, like in the SELECT portion, SELECT '+ cast(#Id as varchar(16)) +'
Also, you code doesn't show where #Id value comes from, so be cautious of SQL injection here.
I am having a hard time grasping why this query is telling me the TaxPayerID is NOT found, when in the beginning, I am clearly checking for it and only using the databases, which should contain the TaxPayerID column in the nTrucks table.
sp_MSforeachdb
'
IF EXISTS (SELECT * FROM [?].INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''nTrucks'' AND COLUMN_NAME = ''TaxPayerID'')
BEGIN
SELECT "?", nTrucks.UnitNumber, ntrucks.Companyid, nCompanyData.CompanyName, nTrucks.Owner, nTrucks.TaxPayerID
FROM nTrucks
INNER JOIN nCompanyData ON nTrucks.CompanyID = nCompanyData.CompanyID
WHERE nTrucks.Owner like ''%Trucker%''
END
'
I am getting multiple 'Invalid column name 'TaxPayerID'.' errors, I assume it is from the databases NOT containing this column.
If anyone here can throw me a bone, a simple "you're a dummy, do it this way!", I would be very appreciative.
JF
You're a dummy! (you asked for it) :)
How to debug this error:
Locate the database that throws an error and try executing an actual SQL query on it directly to see if it will compile:
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''nTrucks'' AND COLUMN_NAME = ''TaxPayerID'')
BEGIN
SELECT nTrucks.UnitNumber, ntrucks.Companyid, nCompanyData.CompanyName, nTrucks.Owner, nTrucks.TaxPayerID
FROM nTrucks
INNER JOIN nCompanyData ON nTrucks.CompanyID = nCompanyData.CompanyID
WHERE nTrucks.Owner like ''%Trucker%''
END
It will fail.
Now you know that SQL server checks schema at query parse time rather than run time.
Then you follow #GordonLinoff suggestion and convert the SELECT query into dynamic SQL as follows:
sp_MSforeachdb
'
IF EXISTS (SELECT * FROM [?].INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''nTrucks'' AND COLUMN_NAME = ''TaxPayerID'')
BEGIN
EXEC(
''SELECT "?", nTrucks.UnitNumber, ntrucks.Companyid, nCompanyData.CompanyName, nTrucks.Owner, nTrucks.TaxPayerID
FROM [?]..nTrucks
INNER JOIN [?]..nCompanyData ON nTrucks.CompanyID = nCompanyData.CompanyID
WHERE nTrucks.Owner like ''''%Trucker%''''
'' )
END
'
(I hope I got my quotes right)
If your query is supposed to reference a central nCompareData table then remove [?].. before nCompareData
I have this situation in a stored Procedure:
SET #DATE_RELEASE_START = '2015-01-01';
SET #DATE_RELEASE_END = '2015-05-31'
SELECT #statement = ' SELECT *
FROM (SELECT AFCDENTE, M.ID_MODIFICATION_CODE, COUNT(*) AS Conteggio--, CAST((COUNT(*) * 100/ 15032) AS decimal(10,7)) AS Percentage
FROM CIC_LOG_MODIFICHE AS L INNER JOIN ADM_MODIFICATION_CODE AS M ON L.CD_MODIFICATION_CODE = M.CD_MODIFICATION_CODE
INNER JOIN CIC_PRODUZIONE AS P ON P.CD_CIC_PRODUZIONE = L.CD_CIC_PRODUZIONE
WHERE AFDTMODI BETWEEN '+#DATE_RELEASE_START+' AND '+#DATE_RELEASE_END+' AND P.CD_PLANT = '+#CD_PLANT+' AND AFCDENTE IS NOT NULL
GROUP BY AFCDENTE, M.ID_MODIFICATION_CODE) as tbl
PIVOT (SUM(tbl.Conteggio) for tbl.ID_MODIFICATION_CODE in (' + #columns + ')) as pvt'
I get this error:
Conversion failed when converting date and/or time from character
string.
I tried casting those dates but no changes. I get the same error.
What should I do?
I'd suggest doing it like that:
SET #DATE_RELEASE_START = '2015-01-01';
SET #DATE_RELEASE_END = '2015-05-31'
SELECT #statement = ' SELECT *
FROM (SELECT AFCDENTE, M.ID_MODIFICATION_CODE, COUNT(*) AS Conteggio--, CAST((COUNT(*) * 100/ 15032) AS decimal(10,7)) AS Percentage
FROM CIC_LOG_MODIFICHE AS L INNER JOIN ADM_MODIFICATION_CODE AS M ON L.CD_MODIFICATION_CODE = M.CD_MODIFICATION_CODE
INNER JOIN CIC_PRODUZIONE AS P ON P.CD_CIC_PRODUZIONE = L.CD_CIC_PRODUZIONE
WHERE AFDTMODI BETWEEN #p0 AND #p1 AND P.CD_PLANT = #p2 AND AFCDENTE IS NOT NULL
GROUP BY AFCDENTE, M.ID_MODIFICATION_CODE) as tbl
PIVOT (SUM(tbl.Conteggio) for tbl.ID_MODIFICATION_CODE in (' + #columns + ')) as pvt'
EXECUTE sp_executesql #statement, N'#p0 DATETIME2, #p1 DATETIME2, #p0 NVARCHAR(1000)', #p0 = #DATE_RELEASE_START, #p1 = #DATE_RELEASE_END, #p2 = #CD_PLANT;
Instead casting them as VARCHAR, just pass them as variables and then use sp_executesql to do the right job.
You must quote the date strings in your SQL code properly:
WHERE AFDTMODI BETWEEN '''+#DATE_RELEASE_START+''' AND '''+#DATE_RELEASE_END+'''
Otherwise the SQL will read
WHERE AFDTMODI BETWEEN 2015-01-01 AND 2015-05-31
instead of
WHERE AFDTMODI BETWEEN '2015-01-01' AND '2015-05-31'
We've also had problems before with passing date/time values to stored procedures in Management Studio. We needed to give the date as 20150101 or 20150531.