Openquery Hung at Same Row Number - sql

I'm attempting to do run an openquery in SQL Server 17 via a linked server to an Oracle connection feed. When I run the query posted below it gets stuck at row 7833 every single time.
Query:
SELECT
sys_ohi,
"Region",
sub_acct_no_ohi,
serv_cde_ohi,
connect_dte_ohi,
charge_amt_ohi
FROM openquery (MyServer, '
(SELECT DISTINCT
sys_ohi,
CASE
WHEN prin_ohi = ''1000'' THEN ''Seattle East''
WHEN prin_ohi = ''1500'' THEN ''Seattle West''
WHEN prin_ohi = ''2000'' THEN ''Oregon''
WHEN prin_ohi = ''3000'' THEN ''Sacramento''
WHEN prin_ohi = ''3500'' THEN ''San Francisco''
END AS "Region",
sub_acct_no_ohi,
serv_cde_ohi,
connect_dte_ohi,
charge_amt_ohi
FROM mytable_ohi
WHERE serv_cde_ohi IN (''INSTALL'')
AND connect_dte_ohi > trunc(to_date(''06-01-2017'',''MM-DD-YYYY'')))')
I have 36 different serv_cde_ohi IN (''INSTALL'') but I have created 36 UNION ALL queries for the different scenarios since attempting to put them within the 'IN' statement was terrible for performance.
I need to know why this query gets stuck at the same spot.

It is possible your UNION ALL declaration is dependent upon implicit data conversions to begin executing, then a data condition occurs during the cursor fetch where the implicit conversion fails in this manner you are observing.
Eliminate all implicit dependencies. For each item in each SELECT, explicitly establish the data types (the same type for each item, ordinally of course).

Related

How to write an Open SQL statement with substring in the JOIN ON condition? [duplicate]

I have the following select statement in ABAP:
SELECT munic~mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE_M ZZONE_T USAGE_M USAGE_T M2MC M2MT M2RET EXEMPTMCMT EXEMPRET CHARGEMCMT
INTO corresponding fields of table GT_INSTMUNIC_F
FROM ZCI00_INSTMUNIC AS MUNIC
INNER JOIN EVER AS EV on
MUNIC~POD = EV~VREFER(9).
"where EV~BSTATUS = '14' or EV~BSTATUS = '32'.
My problem with the above statement is that does not recognize the substring/offset operation on the 'ON' clause. If i remove the '(9) then
it recognizes the field, otherwise it gives error:
Field ev~refer is unknown. It is neither in one of the specified tables
nor defined by a "DATA" statement. I have also tried doing something similar in the 'Where' clause, receiving a similar error:
LOOP AT gt_instmunic.
clear wa_gt_instmunic_f.
wa_gt_instmunic_f-mandt = gt_instmunic-mandt.
wa_gt_instmunic_f-bis = gt_instmunic-bis.
wa_gt_instmunic_f-ab = gt_instmunic-ab.
wa_gt_instmunic_f-zzelecdate = gt_instmunic-zzelecdate.
wa_gt_instmunic_f-ZZCERTDATE = gt_instmunic-ZZCERTDATE.
wa_gt_instmunic_f-CONSYEAR = gt_instmunic-CONSYEAR.
wa_gt_instmunic_f-ZDIMO = gt_instmunic-ZDIMO.
wa_gt_instmunic_f-ZZONE_M = gt_instmunic-ZZONE_M.
wa_gt_instmunic_f-ZZONE_T = gt_instmunic-ZZONE_T.
wa_gt_instmunic_f-USAGE_M = gt_instmunic-USAGE_M.
wa_gt_instmunic_f-USAGE_T = gt_instmunic-USAGE_T.
temp_pod = gt_instmunic-pod.
SELECT vrefer
FROM ever
INTO wa_gt_instmunic_f-vrefer
WHERE ( vrefer(9) LIKE temp_pod ). " PROBLEM WITH SUBSTRING
"AND ( BSTATUS = '14' OR BSTATUS = '32' ).
ENDSELECT.
WRITE: / sy-dbcnt.
WRITE: / 'wa is: ', wa_gt_instmunic_f.
WRITE: / 'wa-ever is: ', wa_gt_instmunic_f-vrefer.
APPEND wa_gt_instmunic_f TO gt_instmunic_f.
WRITE: / wa_gt_instmunic_f-vrefer.
ENDLOOP.
itab_size = lines( gt_instmunic_f ).
WRITE: / 'Internal table populated with', itab_size, ' lines'.
The basic task i want to implement is to modify a specific field on one table,
pulling values from another. They have a common field ( pod = vrefer(9) ). Thanks in advance for your time.
If you are on a late enough NetWeaver version, it works on 7.51, you can use the OpenSQL function LEFT or SUBSTRING. Your query would look something like:
SELECT munic~mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE_M ZZONE_T USAGE_M USAGE_T M2MC M2MT M2RET EXEMPTMCMT EXEMPRET CHARGEMCMT
FROM ZCI00_INSTMUNIC AS MUNIC
INNER JOIN ever AS ev
ON MUNIC~POD EQ LEFT( EV~VREFER, 9 )
INTO corresponding fields of table GT_INSTMUNIC_F.
Note that the INTO clause needs to move to the end of the command as well.
field(9) is a subset operation that is processed by the ABAP environment and can not be translated into a database-level SQL statement (at least not at the moment, but I'd be surprised if it ever will be). Your best bet is either to select the datasets separately and merge them manually (if both are approximately equally large) or pre-select one and use a FAE/IN clause.
They have a common field ( pod = vrefer(9) )
This is a wrong assumption, because they both are not fields, but a field an other thing.
If you really need to do that task through SQL, I'll suggest you to check native SQL sentences like SUBSTRING and check if you can manage to use them within an EXEC_SQL or (better) the CL_SQL* classes.

Snowflake ignores statement in where clause where I'm comparing timestamps

so I'm building a SCD type 2 in snowflake, but it ignores the where clause in which is comparision between "to_timestamp" and "expiry_date". Expiry_date is a variable that is set to '9999-08-17 07:31:29.901000000' (as infinity) and To_timestamp is a column in table. I want to query only the rows that have to_timestamp set to infinity (they are still active) but snowflake seems to ignore this part of where clause. Below is some of the code (it should update the rows that are expired - that means change their "to_timestamp" to current time. and it does but it does to rows with timestamps of all kind - it ignores last line)
SET EXPIRY_DATE_NTZ = '9999-08-17 07:31:29.901000000';
SET CURRENT_DATE_NTZ = TO_TIMESTAMP_NTZ(CURRENT_TIMESTAMP());
UPDATE CUSTOMER_TARGET CT
SET CT.TO_TIMESTAMP = $CURRENT_DATE_NTZ
FROM POC.SNOWFLAKE_POC.CUSTOMER_STAGE CS
WHERE CT.C_CUSTOMER_ID = CS.C_CUSTOMER_ID
AND (CT.C_FIRST_NAME <> CS.C_FIRST_NAME OR CT.C_LAST_NAME <> CS.C_LAST_NAME OR CT.C_BIRTH_YEAR
<> CS.C_BIRTH_YEAR OR CT.C_BIRTH_COUNTRY <> CS.C_BIRTH_COUNTRY OR CT.C_LAST_REVIEW_DATE<>CS.C_LAST_REVIEW_DATE)
AND CT.TO_TIMESTAMP = $EXPIRY_DATE_NTZ;
I have two of these update statements (one for updates and one for deletes) and a merge statement for inserts. And it ignores the comparision in every single one, updating the rows that have "to_timestamp" set to something like "2021-08-24 07:11:53.510000000". I've tried every combination possible (between ... and ..., >= ... <=, <=, >=, comparing in "case" statement of update,...) - nothing. What could be the cause/solution?
As we do not know the structure of CUSTOMER_TARGET I would suggest to explicitly set the data type of EXPIRY_DATE_NTZ variable to match the column data type:
SET EXPIRY_DATE_NTZ = '9999-08-17 07:31:29.901000000';
SELECT $EXPIRY_DATE_NTZ;
DESCRIBE RESULT LAST_QUERY_ID();
to:
-- TIMESTAMP_NTZ as an example
SET EXPIRY_DATE_NTZ = '9999-08-17 07:31:29.901000000'::TIMESTAMP_NTZ;
SELECT $EXPIRY_DATE_NTZ;
DESCRIBE RESULT LAST_QUERY_ID();
By doing that way there are no "implicit conversions" involved in the process.
Another advice is usage of IS DISTINCT FROM instead of <>. IS DISTINCT FROM is NULL safe, which is important if columns are defined as nullable.
UPDATE CUSTOMER_TARGET CT
SET CT.TO_TIMESTAMP = $CURRENT_DATE_NTZ
FROM POC.SNOWFLAKE_POC.CUSTOMER_STAGE CS
WHERE CT.C_CUSTOMER_ID = CS.C_CUSTOMER_ID
AND (CT.C_FIRST_NAME IS DISTINCT FROM CS.C_FIRST_NAME
OR CT.C_LAST_NAME IS DISTINCT FROM CS.C_LAST_NAME
OR CT.C_BIRTH_YEAR IS DISTINCT FROM CS.C_BIRTH_YEAR
OR CT.C_BIRTH_COUNTRY IS DISTINCT FROM CS.C_BIRTH_COUNTRY
OR CT.C_LAST_REVIEW_DATE IS DISTINCT FROM CS.C_LAST_REVIEW_DATE)
AND CT.TO_TIMESTAMP = $EXPIRY_DATE_NTZ;
Your SQL does not have any issues with the filters (ORs are surrounded by the brackets etc). I assume that you have checked the execution profile, and did not see your filter (CT.TO_TIMESTAMP = '9999-08-17 07:31:29.901000000'). In this case, all rows in the target table should have this value in the column TO_TIMESTAMP.
I highly recommend you check the data first. If you are running multiple UPDATE/MERGE commands, you may miss that the data has already updated with this value.

"Circular reference caused by ..." error in Access SQL (but not in T-SQL)

I have the following SQL statement which returns the desired result in SQL Server 2012:
SELECT
S.ONOMA
, S.DIEY
, S.POLH
, S.TK
, S.IDIOT
, S.KODIKOS
, S.AFM
FROM
SYNERG AS S
INNER JOIN
(SELECT
G.AFM, MIN(KODIKOS) AS KODIKOS
FROM SYNERG AS G
WHERE LEN(ISNULL(AFM, '')) != 0
GROUP BY AFM) AS I ON S.KODIKOS = I.KODIKOS
ORDER BY
S.AFM
but when I run the same SQL statement in MS Access 2007 I get an error:
Circular reference caused by 'KODIKOS' in query definition's SELECT list.
Any help would be appreciated.
As explained in the link by HansUp:
The alias of a calculated field cannot be identical to any of the field names used to calculate the field.
This can be rather annoying (esp. if it is a field that is returned by the query), but there is no way around it.
So you need to change the alias, e.g.:
SELECT
S.ONOMA
, S.DIEY
, S.POLH
, S.TK
, S.IDIOT
, S.KODIKOS
, S.AFM
FROM
SYNERG AS S
INNER JOIN
(SELECT
G.AFM, MIN(KODIKOS) AS MinKODIKOS
FROM SYNERG AS G
WHERE LEN(Nz(AFM, '')) <> 0
GROUP BY AFM) AS I ON S.KODIKOS = I.MinKODIKOS
ORDER BY
S.AFM
Note also that an IsNull() function exists in Access, but has a different meaning (it takes one argument and returns a Boolean). The corresponding function is Nz()
And (thanks #HansUp), the unequal operator is <>, not !=. I always use <> in SQL Server too, no need to make things more complicated than necessary. :)

Select #variable not working

I can't seem to wrap my mind around a little situation I have. I am trying to set a variable using an if condition; I have also tried using a case statement as well, but keep receiving error. Below is what I am working with and it's dynamic SQL as well... The variable I am trying to set is #EBP_Allow... Can someone shine some light on this?
What I need it to do for example...
SELECT
#EBP_Allow = IF #Year > 2014 THEN DO a SELECT ELSE DO Something else...
What I have now...
SELECT
#OU_Allow = Optional_Unit_Allowed_Flag,
#BU_Allow = Basic_Unit_Allowed_Flag,
#EU_Allow = Enterprise_Unit_Allowed_Flag,
#WU_Allow = Whole_Farm_Unit_Allowed_Flag,
#EBP_Allow = I NEED TO USE SUB SELECT, IF OR CASE TO SET THIS
FROM dbo.#YEAR_Insurance_Offer
WHERE
(dbo.#YEAR_Insurance_Offer.State_Code = #StateCode) AND
(dbo.#YEAR_Insurance_Offer.County_Code = #CountyCode) AND
(dbo.#YEAR_Insurance_Offer.Crop_Code = ''#CropCode'') AND
(dbo.#YEAR_Insurance_Offer.Insurance_Plan_ID = #PlanId) #TypeCondition #PracticeCondition
Here's an update; it seems that when ran it's still jumping over my condition...
CASE
WHEN #YEAR < 2015
THEN ''N''
WHEN #YEAR > 2014
THEN (
SELECT Enterprise_Unit_By_Practice_Allowed_Flag
FROM dbo.#YEAR_Insurance_Offer
WHERE
(dbo.#YEAR_Insurance_Offer.State_Code = #StateCode) AND
(dbo.#YEAR_Insurance_Offer.County_Code = #CountyCode) AND
(dbo.#YEAR_Insurance_Offer.Crop_Code = ''#CropCode'') AND
(dbo.#YEAR_Insurance_Offer.Insurance_Plan_ID = #PlanId) #TypeCondition #PracticeCondition
)
END
If I replace the WHEN #Year > 2014 with this...
WHEN #YEAR > 2014
THEN ''N''
It work's just fine... For some reason or another when I have the select in there it's telling me that Enterprise_Unit_By_Practice_Allowed_Flag is an invalid column, but it's not?
In order to set #EPB_Allow you can use a CASE statement and you can add multiple WHEN clauses to treat different situations:
SELECT
#OU_Allow = Optional_Unit_Allowed_Flag,
#BU_Allow = Basic_Unit_Allowed_Flag,
#EU_Allow = Enterprise_Unit_Allowed_Flag,
#WU_Allow = Whole_Farm_Unit_Allowed_Flag,
#EBP_Allow = CASE
WHEN #Year > 2014
THEN (SELECT column FROM Table where conditions1...)
WHEN #Year > 2013
THEN (SELECT column FROM Table where conditions2...)
ELSE (SELECT column FROM Table where conditions3...)
END
FROM dbo.#YEAR_Insurance_Offer
WHERE
(dbo.#YEAR_Insurance_Offer.State_Code = #StateCode) AND
(dbo.#YEAR_Insurance_Offer.County_Code = #CountyCode) AND
(dbo.#YEAR_Insurance_Offer.Crop_Code = ''#CropCode'') AND
(dbo.#YEAR_Insurance_Offer.Insurance_Plan_ID = #PlanId)
#TypeCondition #PracticeCondition
Also, make sure that if you have defined #EBP_Allow as NVARCHAR then you have to make sure that the datatype returned by the query which selects what value you want to assign the variable is of the same datatype (otherwise use conversion functions).
And you have to make sure that the query that you specify in the THEN part will return only one result.
OK first it seems you have fallen into the horrible practice of creating new tables with each year. This is a huge database antipattern and if this is the first year you have done this, I suggest an immediate redesign as this just gets harder and harder to deal with as you add more years.
If you can't, well then at least learn from this and never allow anyone to design a table like this in the future. In enterprise level datbase you can partition by date and in smaller ones, you dont need to have differnt tables just a where clause to filter by year and good indexing.
But you seem to be stuck using dynamic SQL to do everything (another reason why this is a horrible design choice). So you might as well learn how to use dynamic SQl correctly.
First read and thorughly understand this link before you try to write code against this database design:
http://www.sommarskog.se/dynamic_sql.html
Here is an example below of how you build and view the generated SQl for a dynamic SQl statement. This will help you corretly build the statement before you try to execute it.
declare #SQl nvarchar (max), #year nchar (4) = '2014'
set #sql = 'SELECT Enterprise_Unit_By_Practice_Allowed_Flag
FROM dbo.' +#YEAR+ '_Insurance_Offer
WHERE dbo.'+ #YEAR + '_Insurance_Offer.State_Code = #StateCode'
Print #sql
Since you are doing this in Stored procs, all of them should be designed with a debug variable that is used to display any SQL built. It doesn't need to run in the debug mode in prodcution, but when you have a problem (and you can't possibly forsee every variable that will ever be part of creating a dynamic sql statement and there is close to a 100% probability that you will encounter wierd bugs that you have to troubleshoot later. So you need to build in troubleshooting ability into every proc you write with dynamic SQl.
Of course to execute you need to learn to use sp_executesql.
But really read the link, share the link with your managers and coworkers and think about better ways to do this.
dbo.#YEAR_Insurance_Offer.State_Code
[databaseowner].[table].[fieldname]
Table name as variable
According to this table names need to be static.
Honestly, I have never seen a variable table name. Further, I can't think of a good reason to do this. So this is either a logic error or a syntax error?

Handle null values within SQL IN clause

I have following sql query in my hbm file. The SCHEMA, A and B are schema and two tables.
select
*
from SCHEMA.A os
inner join SCHEMA.B o
on o.ORGANIZATION_ID = os.ORGANIZATION_ID
where
case
when (:pass = 'N' and os.ORG_ID in (:orgIdList)) then 1
when (:pass = 'Y') then 1
end = 1
and (os.ORG_SYNONYM like :orgSynonym or :orgSynonym is null)
This is a pretty simple query. I had to use the case - when to handle the null value of "orgIdList" parameter(when null is passed to sql IN it gives error). Below is the relevant java code which sets the parameter.
if (_orgSynonym.getOrgIdList().isEmpty()) {
query.setString("orgIdList", "pass");
query.setString("pass", "Y");
} else {
query.setString("pass", "N");
query.setParameterList("orgIdList", _orgSynonym.getOrgIdList());
}
This works and give me the expected output. But I would like to know if there is a better way to handle this situation(orgIdList sometimes become null).
There must be at least one element in the comma separated list that defines the set of values for the IN expression.
In other words, regardless of Hibernate's ability to parse the query and to pass an IN(), regardless of the support of this syntax by particular databases (PosgreSQL doesn't according to the Jira issue), Best practice is use a dynamic query here if you want your code to be portable (and I usually prefer to use the Criteria API for dynamic queries).
If not need some other work around like what you have done.
or wrap the list from custom list et.