Problem getting data from linked server error in SQL - sql-server

I m working in SQL and I have few tables in Oracle database from which I have to get data, so I m doing so via linked server. If I omit date filter then the query works fine but if I apply date filter then it breaks.
This query works fine.
select * from openquery([ORCL], 'select sls_value, retailer_cd, tery_cd, inv_dt
from Toc_cust_second_sls_new where cust_cd IN ( ''1-ZUT42P'' )') secSls --- This query works fine
This query breaks
select * from openquery([ORCL], 'select sls_value, retailer_cd, tery_cd, inv_dt from Toc_cust_second_sls_new where cust_cd IN ( ''1-ZUT42P'' )
and to_date(inv_dt, ''dd/mm/yyyy'') between to_date(''01/05/2020'', ''dd/mm/yyyy'') and to_date(''31/05/2020'', ''dd/mm/yyyy'')') secSls
I get this error.
OLE DB provider "OraOLEDB.Oracle" for linked server "ORCL" returned message "ORA-01861: literal does not match format string".
To filter date I can use this query as it works fine.
select * from openquery([ORCL], 'select sls_value, retailer_cd, tery_cd, inv_dt, inv_no, cust_cd from Toc_cust_second_sls_new
where cust_cd IN ( ''1-ZUT42P'' )') secSls
where convert(date,secSls.inv_dt, 101) >= '2020-05-01' and convert(date,secSls.inv_dt, 101) <= '2020-05-31'
But the problem in the above query is, it first gets all the data from oracle then it filters so there are hundreds if thousands of records which takes a lot of time.

I solved it.
I removed the conversion of inv_dt in oracle as it's data type was already Date, trying to again convert it was creating problem.
select * from openquery([ORCL], 'select sls_value, retailer_cd, tery_cd, inv_dt from Toc_cust_second_sls_new where cust_cd IN ( ''1-ZUT42P'' ) and inv_dt between to_date(''01/05/2020'', ''dd/mm/yyyy'') and to_date(''31/05/2020'',''dd/mm/yyyy'')') secSls
This query works now. Thanks guys who helped me out on comments section.

Related

Sql Server - How do I get JSON nested value in my SQL Select statement

Environment: SQL Server 2014 and above
How do I access the email value in my JSON value with my SELECT statement?
select JSON_VALUE('[{"data":{"email":"test#email.com"}}]', '$.email') as test
Json support was only introduced in SQL Server 2016 - so with any prior version you would need to either use string manipulation code or simply parse the json outside of SQL Server (maybe using a CLR function)
For 2016 version or higher, you can use JSON_VALUE like this:
declare #json as varchar(100) = '[{"data":{"email":"test#email.com"}}]';
select JSON_VALUE(#json, '$[0].data.email') as test
For older versions - you might be able to get away with this, but if your json value does not contain an email property, you will get unexpected results:
select substring(string, start, charindex('"', string, start+1) - start) as test
from (
select #json as string, charindex('"email":"', #json) + 9 as start
) s
You can see a live demo on db<>fiddle
Another way. PatternSplitCM is great for stuff like this.
Extract a single Email value:
DECLARE #json as varchar(200) = '[{"data":{"email":"test#email.com"}}]';
SELECT f.Item
FROM dbo.patternsplitCM(#json,'[a-z0-9#.]') AS f
WHERE f.item LIKE '%[a-z]%#%.%[a-z]%'; -- Simple Email Check Pattern
Extracting all Email Addresses (if/when there are more):
DECLARE #json VARCHAR(200) = '[{"data":{"email":"test#email.com"},{"email2":"test2#email.net"}},{"data":{"MoreEmail":"test3#email.555whatever"}}]';
SELECT f.Item
FROM dbo.patternsplitCM(#json,'[a-z0-9#.]') AS f
WHERE f.item LIKE '%[a-z]%#%.%[a-z]%'; -- Simple Email Check Pattern
Returns:
Item
--------------------------
test#email.com
test2#email.net
test3#email.555whatever
Or... the get only the first Email address that appears:
SELECT TOP (1) f.Item
FROM dbo.patternsplitCM(#json,'[a-z0-9#.]') AS f
WHERE f.item LIKE '%[a-z]%#%.%[a-z]%' -- Simple Email Check Pattern
ORDER BY ROW_NUMBER() OVER (ORDER BY f.ItemNumber)
Nasty fast, super-simple. No cursors, loops or other bad stuff.
With v2014 there is no JSON support, but - if your real JSON is that simple - it is sometimes a good idea to use some replacements in order to transform the JSON to XML like here, which allows for the native XML methods:
DECLARE #YourJSON NVARCHAR(MAX)=N'[{"data":{"email":"test#email.com"}}]';
SELECT CAST(REPLACE(REPLACE(REPLACE(REPLACE(#YourJSON,'[{"','<'),'":{"',' '),'":"','="'),'}}]',' />') AS XML).value('(/data/#email)[1]','nvarchar(max)');
It can be done in two ways:
First, if your JSON data is between [ ] like in your question:
select JSON_VALUE('[{"data":{"email":"test#email.com"}}]','$[0].data.email' ) as test
And if your JSON data is not between [ ]:
select JSON_VALUE('{"data":{"email":"test#email.com"}}','$.data.email' ) as test
You can teste the code above here
Your query should be like this (SQL Server 2016):
DECLARE #json_string NVARCHAR(MAX) = 'your_json_value'
SELECT [key],value
FROM OPENJSON(#json_string, '$.email'))
UPDATE :
select JSON_VALUE(#json_string, '$[0].data.email') as test

SSRS: How to find which reports have subreports?

I have a lot of SQL Server Reporting Services (SSRS) reports (*.rdl). I want to know which of these reports are using subreports. How can I do that? Looking at an easier way instead of opening each report and figuring out if a subreport is being used.
Thanks
I think this should provide you with what you need (With thanks to Bret Stateham ):
--The first CTE gets the content as a varbinary(max)
--as well as the other important columns for all reports,
--data sources and shared datasets.
WITH ItemContentBinaries AS
(
SELECT
ItemID,Name,[Type]
,CASE Type
WHEN 2 THEN 'Report'
WHEN 5 THEN 'Data Source'
WHEN 7 THEN 'Report Part'
WHEN 8 THEN 'Shared Dataset'
ELSE 'Other'
END AS TypeDescription
,CONVERT(varbinary(max),Content) AS Content
FROM ReportServer.dbo.Catalog
WHERE Type IN (2,5,7,8)
),
--The second CTE strips off the BOM if it exists...
ItemContentNoBOM AS
(
SELECT
ItemID,Name,[Type],TypeDescription
,CASE
WHEN LEFT(Content,3) = 0xEFBBBF
THEN CONVERT(varbinary(max),SUBSTRING(Content,4,LEN(Content)))
ELSE
Content
END AS Content
FROM ItemContentBinaries
)
--The outer query gets the content in its varbinary, varchar and xml representations...
,VarcharContent as
(
SELECT
ItemID,Name,[Type],TypeDescription
,Content --varbinary
,CONVERT(varchar(max),Content) AS ContentVarchar --varchar
,CONVERT(xml,Content) AS ContentXML --xml
FROM ItemContentNoBOM
)
SELECT * FROM VarcharContent where ContentVarchar like '%<subreport%'
The following query below will return a list of deployed reports that have subreports. Here's the Microsoft reference and a link for referencing older versions of SSRS. It looks like the only difference is changing the version of SSRS in XMLNAMESPACES part of the CTE.
Query to return all subreports
WITH
XMLNAMESPACES
(
'http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition' AS rdl
)
,
report_list
AS
(
SELECT
[ReportID] = cat.[ItemID]
, [ReportName] = cat.[Name]
, [ReportPath] = cat.[Path]
, [xmlColumn] = CAST(CAST(cat.[Content] AS VARBINARY(MAX)) AS XML)
FROM
[ReportServer].[dbo].[Catalog] AS cat
WHERE
1=1
AND cat.[Content] IS NOT NULL
AND cat.[Type] = 2
)
SELECT
rpt.[ReportID]
, rpt.[ReportName]
, rpt.[ReportPath]
, [SubReportName] = srpt.x.value('(//rdl:ReportName)[1]', 'NVARCHAR(256)')
FROM
report_list AS rpt
CROSS APPLY xmlColumn.nodes('//rdl:Subreport') AS srpt(x);

BigQuery or SQL Server SPLIT query

I have searched around and can not find much on this topic. I have a table, that gets logging information. As a result the column I am interested in contains multiple values that I need to search against. The column is formatted in a php URL style. i.e.
/test/test.aspx?DS_Vendor=55039&DS_ProdVer=7.90.100.0&DS_ProdLang=EN&DS_Product=MTT&DS_OfficeBits=32
This makes all searches end up with really long regexes to get data. Then join statements to combine data.
Is there a way in BigQuery, or SQL Server that I can pull the information from that column and put it into new columns?
Example:
The information I would like extracted begins after the ?, and ends at &, The string can sometimes be longer, and contains additional headers.
Thanks,
Below is for BigQuery Standard SQL and addresses below aspect of your question
Is there a way in BigQuery, ... that I can pull the information from that column and put it into new columns?
#standardSQL
CREATE TEMP FUNCTION parseColumn(kv STRING, column_name STRING) AS (
IF(SPLIT(kv, '=')[OFFSET(0)]= column_name, SPLIT(kv, '=')[OFFSET(1)], NULL)
);
WITH `project.dataset.table` AS (
SELECT '/test/test.aspx?extra=abc&DS_Vendor=55039&DS_ProdVer=7.90.100.0&DS_ProdLang=EN&DS_Product=MTT&DS_OfficeBits=32' AS url UNION ALL
SELECT '/test/test.aspx?DS_Vendor=55192&DS_ProdVer=4.30.100.0&more=123&DS_ProdLang=DE&DS_Product=MTE&DS_OfficeBits=64'
)
SELECT
MIN(parseColumn(kv, 'DS_Vendor')) AS DS_Vendor,
MIN(parseColumn(kv, 'DS_ProdVer')) AS DS_ProdVer,
MIN(parseColumn(kv, 'DS_ProdLang')) AS DS_ProdLang,
MIN(parseColumn(kv, 'DS_Product')) AS DS_Product,
MIN(parseColumn(kv, 'DS_OfficeBits')) AS DS_OfficeBits
FROM `project.dataset.table`,
UNNEST(REGEXP_EXTRACT_ALL(url, r'[?&]([^?&]+)')) AS kv
GROUP BY url
with the result as below
Row DS_Vendor DS_ProdVer DS_ProdLang DS_Product DS_OfficeBits
1 55039 7.90.100.0 EN MTT 32
2 55192 4.30.100.0 DE MTE 64
Below is also addressed
The string can sometimes be longer, and contains additional headers.
One example using BigQuery (with standard SQL):
SELECT REGEXP_EXTRACT_ALL(url, r'[?&]([^?&]+)')
FROM (
SELECT '/test/test.aspx?DS_Vendor=55039&DS_ProdVer=7.90.100.0&DS_ProdLang=EN&DS_Product=MTT&DS_OfficeBits=32' AS url
)
This returns the parts of the URL as an ARRAY<STRING>. To go one step further, you can get back an ARRAY<STRUCT<key STRING, value STRING>> with a query of this form:
SELECT
ARRAY(
SELECT AS STRUCT
SPLIT(part, '=')[OFFSET(0)] AS key,
SPLIT(part, '=')[OFFSET(1)] AS value
FROM UNNEST(REGEXP_EXTRACT_ALL(url, r'[?&]([^?&]+)')) AS part
) AS keys_and_values
FROM (
SELECT '/test/test.aspx?DS_Vendor=55039&DS_ProdVer=7.90.100.0&DS_ProdLang=EN&DS_Product=MTT&DS_OfficeBits=32' AS url
)
...or with the keys and values as top-level columns:
SELECT
SPLIT(part, '=')[OFFSET(0)] AS key,
SPLIT(part, '=')[OFFSET(1)] AS value
FROM (
SELECT '/test/test.aspx?DS_Vendor=55039&DS_ProdVer=7.90.100.0&DS_ProdLang=EN&DS_Product=MTT&DS_OfficeBits=32' AS url
)
CROSS JOIN UNNEST(REGEXP_EXTRACT_ALL(url, r'[?&]([^?&]+)')) AS part

SQL Server FOR/AFTER trigger

I have an issue with an assignment. I believe I have the code all worked out properly but I keep getting a syntax error saying that the column "Total" Does not exist. I was under the impression that when you used "AS" it renamed the column that you are trying to use.
Here is my code any pointers would be greatly appreciated.
Use [IST278EagleCorp13-1]
Go
Alter Trigger DPInvOrderTrigger
On InventoryPart
For insert
As
If exists ( Select Count(ReorderLevel * 4) ReorderLevel,Count(StockOnOrder + StockLevel) AS Total
From InventoryPart
Where Total > ReorderLevel)
Begin
RaisError('Inventory to low. Transaction failed.',16,1)
rollback tran
End
These are the directions for this assignment.
/* Create a FOR|AFTER trigger named xxInvOrderTrigger for updates
to the InventoryPart table. If an update produces a record where
the (stockOnOrder + stockLevel) > (4 * reorderLevel) raise an
error (display an error) and rollback the change. */
To my understanding you are using SQL Server as your RDBMS and if I am not wrong in your below query Total is a column alias and you can't use column alias in where clause. That's why the error is for.
See a sample fiddle here for your understanding http://sqlfiddle.com/#!3/f902c/1
Select Count(ReorderLevel * 4) ReorderLevel,
Count(StockOnOrder + StockLevel) AS Total
Rather you can do it using derived table like below
select ReorderLevel,
Total
from
(
Select Count(ReorderLevel * 4) ReorderLevel,
Count(StockOnOrder + StockLevel) AS Total,
ReorderLevel
From InventoryPart
) tab
Where Total > ReorderLevel

Update on linked server with nested subquery

I want to update on a linked server the result of a query as well from a linked server.
The first sql snippet gives me the value to be updated:
SELECT mmdb_vessel.IMONo, mmdb_vessel.DeathDate
From OPENQUERY(MMDB, 'SELECT FunctionalLocation, IMONo, VesselStatus, CONVERT(VARCHAR(10), DeathDate, 102) AS DeathDate
FROM VESSEL
WHERE VESSEL.VesselStatusID <> 42 AND VESSEL.DeathDate is not null') as mmdb_vessel
, eb_all_v
WHERE
eb_all_v.IMO_No = mmdb_vessel.IMONo
AND eb_all_v.status = 'in service'
the second is actually what I'm not able to implement, it should show what I want to achieve:
UPDATE EPI2..EPI.PLANT
SET KIND_OF_LIQUIDATION_NO = 1
, LIQUIDATION_DATE = [result from snippet above].DeathDate
Where EPI2..EPI.PLANT.IMONo = [result from snippet above].IMONo
I'm not so sure if my explanation is sufficient, please feel free to ask for additional information!
Thanks, already in advance,
Werner
I would recommend to select the data from the remote server first and store the required data e.g. in a temptable, because LinkedServer and updates can have some sideeffects (e.g. performing a tablescan on the remote table, altough you would not expect it if an updaet is involved, etc) - but this depends on your exact usage/scenario.
Select data you need to update
SELECT * INTO #tmpTable FROM LINKEDSERVER.EPI.dbo.PLANT WHERE ....
Perform the update on local server
UPDATE EPI2..EPI.PLANT SET KIND_OF_LIQUIDATION_NO = 1, LIQUIDATION_DATE = t.DeathDate FROM #tmpTable t INNER JOIN EPI2..EPI.PLANT p on t.IMONo = p.IMONo

Resources