LEFT join on secure view fails in snowflake - snowflake-cloud-data-platform

I have a normal view and one secure view and a table.
create or replace NORMALVIEW as select click_id FROM SECURE_VIEW a
LEFT JOIN
TABLE e
ON (e.click_id = a.google_click_id);
select * from NORMALVIEW;
I am getting the error:
SQL execution internal error: Processing aborted due to error 300002:2523989150; incident 8846932.
other operations such as union is working

If you got an incident then you will need to open a case with Snowflake support to understand what is happening.

So I assume the SELECT part is valid:
select e.click_id
FROM SECURE_VIEW a
LEFT JOIN TABLE e
ON (e.click_id = a.google_click_id);
I also assume the view is actually defined more like:
CREATE table test.test.table_name (click_id int);
insert into test.test.table_name values (0),(1);
CREATE SECURE VIEW test.test.SECURE_VIEW AS
SELECT click_id as google_click_id
FROM test.test.table_name
WHERE click_id%2 = 1;
CREATE VIEW test.test.NORMALVIEW AS
SELECT click_id
FROM test.test.SECURE_VIEW AS a
LEFT JOIN test.test.table_name AS e
ON e.click_id = a.google_click_id;
Or some other all valid stuff, thus those views would not be created. for the select to fail on.
I wonder if you grab the DDL of the view and try recreate then (with different names) if they are still valid, or if the shape of some underlying table changed, or if something as be drop/recreate/renamed..
SELECT * from NORMALVIEW;
But yes, at the point open a support ticket.

Related

SQL Server: Update where exists and Insert when not exists

I have 2 tables, one is called
INTER and the other one is called COM
The relationship between them is 1:many
Here's the structure of both tables
INTER
NUMBER
ADDRESS
COM
NUMBER
CONTACT
REFERENCE
To give some context about the tables:
The ADDRESS field from the INTER table can be empty (empty string '')
The CONTACT field of the COM table can be of two types: "E-mail" or "Website"
What I'm trying to accomplish is the following:
I want to look at all the records from COM where CONTACT='Website' and insert into COM the values of (INTER.NUMBER,'Website',INTER.ADDRESS)
where INTER.ADDRESS<>'' and INTER.NUMBER does not exist in COM.NUMBER
Otherwise, I want to update the value of COM.REFERENCE, set it to INTER.ADDRESS where COM.CONTACT='Website' and INTER.NUMBER exists in COM.NUMBER and INTER.ADDRESS<>''
How can I accomplish this? I know what the merge statement is but according to the documentation merge does not work well on filtered queries. Also, I know about the exists statement but I don't know how to make this query work.
In case you're wondering, unfortunately, the structure of these tables cannot be modified.
Some sample data:
INTER
ABCD123,google.com
XUEH342,facebook.com
IISI521,twitter.com
IEIEK885,''
COM
ABCD123, Website, test.com
ABCD123,E-mail,bob#gmail.com
XUEH342,Website,facebook.com
XASE456,Website, stackoverflow.com
XASE456,E-mail,tom#gmail.com
After running the query, the results on COM table would look as the following:
ABCD123,Website, google.com
ABCD123,E-mail,bob#gmail.com
XUEH342,Website, facebook.com
IISI521,Website, twitter.com
XASE456,Website, stackoverflow.com
XASE456,E-mail,tom#gmail.com
As you can see, IISI521,twitter.com got inserted,ABCD123,test.com got updated and IEIEK885,'' didn't get inserted because is an empty string.
You can try below query:
MERGE com with (HOLDLOCK) AS cm
USING (SELECT a.number, a.address, b.contact FROM inter a left join com b on a.number = b.number and b.contact = 'website' WHERE a.address != '' ) AS intr
ON cm.number = intr.number and cm.contact = intr.contact
WHEN MATCHED THEN
UPDATE
SET cm.reference = intr.address
WHEN NOT MATCHED THEN
INSERT
(
number,
contact,
reference
)
VALUES
(
intr.number,
'website',
intr.address
);

How to find rows in ms-sql with another rows' value followingly?

I have created an Sql table to trace objects' operation history. I have two columns; first one is the self tracing code and second tracing code is the tracing code for the code coming from source object to target. I created this to be able to look up the route of operations through the objects. You can see the tracing sample table below:
I need to create an sql code to query to show all the route in one table. When I first select the self code, it will be the incoming code for previous rows. There may be more than one incoming code to self and I want to be able to trace all. And I want to reach end until my search is null.
I tried select query like below but I am so new sql and need your help.
SELECT [TracingCode.Self],
[TracingCode.Incoming],
[EquipmentNo]
FROM [MKP_PROCESS_PRODUCT_REPORTS].[dbo].[ProductionTracing.Main]
WHERE [TracingCode.Self] = (SELECT [TracingCode.Incoming]
FROM [MKP_PROCESS_PRODUCT_REPORTS].[dbo].[ProductionTracing.Main]
WHERE [TracingCode.Self] = (SELECT [TracingCode.Incoming]
FROM [MKP_PROCESS_PRODUCT_REPORTS].[dbo].[ProductionTracing.Main]
WHERE [TracingCode.Self] = (SELECT [TracingCode.Incoming]
FROM [MKP_PROCESS_PRODUCT_REPORTS].[dbo].[ProductionTracing.Main]
WHERE [TracingCode.Self] = '028.001.19.2.3')));
To do this kind of parent/child thing to any level without explicitly coding all levels you need to use a recursive CTE.
More details here
https://www.red-gate.com/simple-talk/sql/t-sql-programming/sql-server-cte-basics/
Here is some test data and a solution I came up with. Note that three records actually match 028.001.19.2.3
If this doesn't do what you need please explain further with sample data.
DECLARE #Sample TABLE (
TC_Self CHAR(14) NOT NULL,
TC_In CHAR(14) NOT NULL,
EquipmentNo INT NOT NULL
);
INSERT INTO #Sample (TC_Self, TC_In, EquipmentNo)
VALUES
('028.001.19.2.3','026.003.19.2.2',96),
('028.001.19.2.3','026.001.19.2.2',96),
('028.001.19.2.3','026.002.19.2.2',96),
('028.001.19.2.2','026.002.19.2.1',96),
('028.001.19.2.2','026.002.19.2.1',96),
('028.001.19.2.1','026.002.19.1.1',96),
('026.003.19.2.2','024.501.19.2.5',117),
('024.501.19.2.5','024.501.19.2.6',999),
('024.501.19.2.6','024.501.19.2.7',998);
WITH CTE (RecordType, TC_Self, TC_In, EquipmentNo)
AS
(
-- This is the 'root'
SELECT 'Root' RecordType, TC_Self, TC_In, EquipmentNo FROM #Sample
WHERE TC_Self = '028.001.19.2.3'
UNION ALL
SELECT 'Leaf' RecordType, S.TC_Self, S.TC_In, S.EquipmentNo FROM #Sample S
INNER JOIN CTE
ON S.TC_Self = CTE.TC_In
)
SELECT * FROM CTE;
Also please note that most of the time to generate this answer was taken in generating the sample data to use.
In future when asking questions, people are far more likely to help if you post this sample data generation yourself

SQL Duplicate column names error in Create View, even with aliases

The error is oddly specific, but I've just about honed in where it's occurring. The standard fix doesn't seem to be working though.
Here's where the error occurs. It's a big statement, so I'm just posting where I've found the error
CREATE OR REPLACE VIEW SalesInvoiceDoc
AS
( SELECT si.salinv_Num, si.salinv_Terms, si.salinv_SaleDate,
es.empName AS SalesAgent, man.empName AS ApprovingManager,
si.salinv_ApproveDate, ...
... FROM service_invoice si
JOIN employee es
ON (es.empID = si.salinv_EmpID)
JOIN employee man
ON (man.empID = si.salinv_ManID)
Essentially it's a Sales invoice document with a sales agent and approving manager. Both are stored in the employee table with a subtype discriminator set up for 'manager' or 'sales', and views for the subtype children tables to avoid duplication errors.
I've supplied aliases to try and avoid duplicate columns, but when I run this script, I get the duplicate column names error:
ORA-00957: duplicate column name
Does anyone know how to resolve this? Is it even possible? Any help would be greatly appreciated. Thank you in advance!
Edit: here's the full statement
CREATE OR REPLACE VIEW SalesInvoiceDoc
AS
( SELECT si.salinv_Num, si.salinv_Terms, si.salinv_SaleDate,
es.empName AS SalesAgent,
man.empName AS ApprovingManager, si.salinv_ApproveDate,
sc.custName, sc.custHouse, sc.custCity,
sc.custState, sc.custZIP, sc.custPhone, sc.custEmail,
sv.vehicle_VIN, sv.vehicle_year, sv.vehicle_make,
sv.vehicle_model, sv.vehicle_ext_color, sv.vehicle_trim,
sv.vehicle_list_base_price, sv.vehicle_mileage, sv.vehicle_condition,
sv.vehicle_description,
ti.vehicle_make, ti.vehicle_year, ti.vehicle_model, ti.vehicle_VIN,
ti.tradein_allowance,
sv.vehicle_list_base_price "SellingPrice", sv.shipping "Shipping",
ti.tradein_allowance "TradeAllowance",
(sv.vehicle_list_base_price + sv.shipping - ti.tradein_allowance) "Subtotal",
(sv.vehicle_list_base_price + sv.shipping - ti.tradein_allowance)*.0825 "Taxes",
(sv.vehicle_list_base_price + sv.shipping - ti.tradein_allowance)*1.0825 "TotalSellingPrice"
FROM sales_invoice si
JOIN employee es
ON (es.empID = si.salinv_EmpID)
JOIN employee man
ON (man.empID = si.salinv_ManID)
JOIN customer sc
ON (sc.custID = si.salinv_CustID)
JOIN vehicle sv
ON (sv.vehicle_VIN = si.salinv_SalVIN)
LEFT OUTER JOIN vehicle ti
ON (ti.vehicle_VIN = si.salinv_tiVIN)
);
You are duplicating column names from 2 different tables:
sv.vehicle_VIN,
sv.vehicle_year,
sv.vehicle_make,
sv.vehicle_model
and
ti.vehicle_make,
ti.vehicle_year,
ti.vehicle_model,
ti.vehicle_VIN
The resulting column name does not include the table alias.
Issue is cause sv.vehicle_VIN is appearing twice in your query and so does other columns. See below. You need to alias them all accordingly
**sv.vehicle_VIN**, **sv.vehicle_year**, **sv.vehicle_make**, **sv.vehicle_model**,
**ti.vehicle_make**, **ti.vehicle_year**, **ti.vehicle_model**, **ti.vehicle_VIN**,

How to create VIEW in MS Access Database using Delphi Application without installing MSAccess on PC?

I want to create VIEW definitions on MS Access. I have used following CREATE VIEW Statement:
SELECT
MFP.FollowUpPlan_Id,
MFP.FollowUpPlan_Name AS PlanName,
DFP.Sequence_No AS SequenceNo,
MFS.FollowUpSchedule_Name AS ScheduleName
FROM
MAS_FollowUp_Plan AS MFP,
DET_FollowUp_Plan AS DFP,
MAS_FollowUp_Schedule AS MFS
WHERE
(((MFP.FollowUpPlan_Id)=DFP.FollowUpPlan_Id) AND
((DFP.FollowUpSchedule_Id)=MFS.FollowUpSchedule_Id)) AND
MFP.is_Deleted = FALSE AND
DFP.is_Deleted = false
ORDER BY
MFP.FollowUpPlan_Id, DFP.Sequence_No;
but it throw an error:
Only Simple Select Queries are allowed in view.
Please Help, Thanks in Advance.
The issue here, as Jeroen explained, is a limitation of Access' CREATE VIEW statement. For this case, you can use CREATE PROCEDURE instead. It will create a new member of the db's QueryDefs collection --- so from the Access user interface will appear as a new named query.
The following statement worked for me using ADO from VBScript. From previous Delphi questions on here, my understanding is that Delphi can also use ADO, so I believe this should work for you, too.
CREATE PROCEDURE ViewSubstitute AS
SELECT
MFP.FollowUpPlan_Id,
MFP.FollowUpPlan_Name AS PlanName,
DFP.Sequence_No AS SequenceNo,
MFS.FollowUpSchedule_Name AS ScheduleName
FROM
(MAS_FollowUp_Plan AS MFP
INNER JOIN DET_FollowUp_Plan AS DFP
ON MFP.FollowUpPlan_Id = DFP.FollowUpPlan_Id)
INNER JOIN MAS_FollowUp_Schedule AS MFS
ON DFP.FollowUpSchedule_Id = MFS.FollowUpSchedule_Id
WHERE
MFP.is_Deleted=False AND DFP.is_Deleted=False
ORDER BY
MFP.FollowUpPlan_Id,
DFP.Sequence_No;
You cannot mix ORDER BY with JOIN when creating views in Access. It will get you the error "Only simple SELECT queries are allowed in VIEWS." (note the plural VIEWS)
Having multiple tables in the FROM is a kind of to JOIN.
either remove the ORDER BY,
or have only one table in the FROM and no JOINs.
I remember from the past (when I did more Access stuff than now) seeing this for a large query with a single table select with an ORDER BY as well.
The consensus is that you should not have ORDER BY in views anyway, so that is your best thing to do.
Another reason that you can get the same error message is if you add parameters or sub selects. Access does not like those in views either, but that is not the case in your view.
Declare variable olevarCatalog ,cmd as OleVariant in Delphi, Uses ComObj
olevarCatalog := CreateOleObject('ADOX.Catalog');
olevarCatalog.create(YourConnectionString); //This Will create MDB file.
// Using ADO Query(CREATE TABLE TABLEName....) add the required Tables.
// To Insert View Definition on MDB file.
cmd := CreateOleObject('ADODB.Command');
cmd.CommandType := cmdText;
cmd.CommandText := 'ANY Kind of SELECT Query(JOIN, OrderBy is also allowed)';
olevarCatalog.Views.Append('Name of View',cmd);
cmd := null;
This is a best way to Create MS ACCESS File(.MDB) and VIEWs using Delphi.

Stored Procedure with two input params and multiple matches and create view with in

I am not much strong in SQL, so looking for some help.
First I am looking for suggestion for the best way to implement this logic in SQL and then some sample code to implement.
My portal is going to connect Students and Training Providers.
Students: Select what courses (multiple) they want, type of delivery (online, class room), Industry(domain) to which the course to be targeted more, Location Preference.
Training Providers: Select what courses offering (so one record for each course), offering locations, type of delivery for each course, industries (multiple) it is targeting.
When student login:
I would like to create SP which in turn create view to store the matched records of the Training Providers data which matches that student needs of that StudentID, CourseID passed to SP
I have created the following sp ( but not included create view part as I am not sure how to do this)
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER PROCEDURE [dbo].[sp_TPsMatched2StuCourse]
-- Add the parameters for the stored procedure here
#StuID int,
#CourseID int
AS
BEGIN
Select TP.MemID,TP.PastExp,SN.DeliveryType,SN.LocPref,SN.Industry,SC.CourseID from
tbl_TrainingProvider as TP , tbl_StuCourses as SC, tbl_StuNeeds SN
where SN.CourseID = #CourseID and SN.StuID = #StuID and
SN.DeliveryType in (TP.DeliveryMode) and
SN.LocPref IN (TP.LocOffering) and
SN.Industry IN (TP.Industries)
END
--- exec sp_ELsMatched2EntProp 1, 1
Why I need to put the data is as follows:
Assume the data is stored in that dynamic view and that would be bind to datagrid. Student then select interested TPs. Then only contact details would be shared to each other and this cannot be reveresed. So I would put this interested data in another table later. Every time data changes, hence the matches. Student can change some of his/her needs or new TPs join etc so view to be temparory.
when I executed this using above command, I am not getting data though it matches few records. What is wrong I am doing.
Any help would be greatly appreciated.
You are not getting expected results because you filter out too many records in WHERE( I'm talking about this part : SN.DeliveryType in (TP.DeliveryMode) and
SN.LocPref IN (TP.LocOffering) and SN.Industry IN (TP.Industries)). I'd recommend to use JOIN ... ON instead of specifying all tables in FROM and join condition in WHERE. I'm not sure what you want exactly, but I believe you are looking for
FROM tbl_StuNeeds SN
LEFT JOIN tbl_TrainingProvider as TP ON (TP.DeliveryMode = SN.DeliveryType AND
SN.LocPref = TP.LocOffering AND TP.Industries = SN.Industry)
WHERE SN.CourseID = #CourseID and SN.StuID = #StuID
Also, there is no join conditions in your code for tbl_StuCourses as SC which results in cross-join.
Finally, why do you need a stored procedure at all? From what I see in your example, a table-valued function will work better:
CREATE FUNCTION [dbo].getTPsMatched2StuCourse(#StuID INT,#CourseID INT)
RETURNS TABLE AS
RETURN
Select .... ;

Resources