Materialized View is coming as invalid materialized view definition in Snowflake - snowflake-cloud-data-platform

SQL compilation error: error line 0 at position -1 Invalid materialized view definition. More than one table referenced in the view definition
Materialized View is coming as invalid materialized view definition in Snowflake. What is the alternate approach if we want to query more than one table??
create or replace procedure mv_test()
returns string
language javascript
execute as caller
as
$$
function log (msg) {
snowflake.createStatement( { sqlText: `call do_log ( :col1, :col2 )`, binds:[ 'mv_test', msg ] } ).execute();
}
try
{
CALL DBMS_MVIEW.REFRESH('mv1');
}
catch (err)
{
console.error ('Error :,',(+ err.code+' '+ err.message));
return} }
$$;
The Oracle SP script for the above is:
create or replace PROCEDURE test_sp_orcl As
BEGIN
DBMS_MVIEW.REFRESH('mv1');
END test_sp_orcl;
We are using more than 1 table to create the materialized view in Oracle. But the same approach will not work in Snowflake as the materialized view in Snowflake can query only a single table.
Any suggestions would be helpful.

Materialized View is coming as invalid materialized view definition in Snowflake. What is the alternate approach if we want to query more than one table?
A materialized view can query only a single table.
https://docs.snowflake.com/en/user-guide/views-materialized.html#limitations-on-creating-materialized-views
You can create a task to store the output of your query to a table, and refresh it periodically.

Related

Data is not being loaded to Snowflake

So I managed to load data by the snowflake CLI, but I want to automatize this.
From what I read, I can load data using SQL statements (My table is, at the moment, with 1 column: V VARIANT) and I'm loading data like this:
order => {
connection.execute({
sqlText: `INSERT INTO "xx"."xx"."xx" VALUES(${order})` //Also tried only with the tablename
}
But when I query everything from the table, it's empty. Why is that?

Is it possible to ignore errors on DROP VIEW IF EXISTS xxx (Object found is of type TABLE)?

If have a
DROP VIEW IF EXISTS mydatabase.myschema.myname;
CREATE OR REPLACE TABLE mydatabase.myschema.myname AS ...
that fails with error code 2203 SQL compilation error: Object found is of type 'TABLE', not specified type 'VIEW'..
My intention was to create a script to "convert" a set of existing views into tables (updated periodically via tasks). I wanted the script to be repeteable, so I thought I could DROP VIEW IF EXISTS xxx to drop the view if it exists but it seems that this will fail if there is already a table of the same name. So first time the script runs ok, it drops the view and creates the table but if I run the script again it will fail because now there is table with that same name.
So is there any way to ignore the error in the DROP VIEW IF EXISTS xxx or just to run the command if there is a VIEW with that name?
You have a number of options.
You can have your script read from the INFORMATION_SCHEMA to get a list of views and to delete. This SQL gets a list of all views except in the INFORMATION_SCHEMA.
select * from INFORMATION_SCHEMA.VIEWS where TABLE_SCHEMA <> 'INFORMATION_SCHEMA';
If you just want to drop the view names and avoid running into errors, here's a stored procedure you can call to try dropping a view without generating an error:
create or replace procedure DropView(viewName string)
returns string
language JavaScript
execute as OWNER
as
$$
var sql_command =
'drop view ' + VIEWNAME;
try {
var stmt = snowflake.createStatement( {sqlText: sql_command} );
var resultSet = stmt.execute();
while (resultSet.next()) {
outString = resultSet.getColumnValue('status');
}
}
catch (err) {
outString = err; // Return a success/error indicator.
}
return outString;
$$;
If you want to loop through every database and schema in the entire account, I wrote a stored procedure to do that. It's designed for dependency checking on all views, but could be modified to delete them too.
https://snowflake.pavlik.us/index.php/2019/10/14/object-dependency-checking-in-snowflake
My suggestion would be to create a stored procedure that loops through all of your views and creates tables from them. In that stored procedure, you could check to see if the object exists already as a table and skip that object.

How to create schema binding and index on view from other server?

I have tried creating a view with the help of schema binding and indexing which is referring from other server table. But sql thrown some error for the below query .
create VIEW [dbo].[Vxyz]
with schemabinding
AS
SELECT
ELID,USECOUNT,LASTUPDATE,TYPE,CODENE,CASNUE,NAME_ENG,ISGROUP,CHGROUP,DLink
IDE,LOCKBY,PhyApB,BUILDNO,PMNNumE,EINECE
FROM IADL.dbo.tblxyz
GO
create unique clustered index IDX_xyz on [dbo].
[Vxyz](ELID)
Found below error
Msg 4512, Level 16, State 3, Procedure IADL.dbo.tblxyz, Line 3 [Batch Start Line 11]
Cannot schema bind view '[dbo].[Vxyz]' because name 'IADL.dbo.tblxyz' is invalid for schema binding. Names must be in two-part format
and an object cannot reference itself.
Msg 1939, Level 16, State 1, Line 17
Cannot create index on view '[dbo].[Vxyz]' because the view is not schema bound.
select distinct
ISNULL(A.elid, B.elid) ElementID,
CASE when A.elid is null and B.elid is not null then 'Missing ElementID :'+
B.elid+' in Mainproductsall table' when A.elid is not null
and B.elid is null then 'Missing ElementID :'+ A.elid+' in Genproductsall table' Else 'OK'
end Datastatus
into ABC
from [dbo].[Vxyz] As A
full outer join [dbo].[Vxyzwa] as B on A.elid = B.elid
where A.elid is null or B.elid is null
Each from from above query is view . As per my first query above which is referring from other server. so i want to optimize and i am trying to create index.
If you check official documentation, you will see that it is stated as follows
All referenced objects must be in the same database.
So you cannot refer a base table from an other database.
This means, for all referenced current database objects should be referenced with their schema name and object name.

SQL Server : get messages from referenced entities procedure in code

I'm running big dependency scan on legacy db and see that some objects have obsolete ref links, if you run this code in SSMS for View that points to not existing table like in my case, you will get your output on Results tab AND error info in Messages . Like in my case below.
I tried to check all env things I know and output of this stored procedure, but didn't see any indication.
How I can capture this event as I'm running this in looped dynamic SQL script and capture output in my table for further processing?
Updated:
it just text in Message box ,on error, you still have output on
Results tab
this is sp, it loop thru object list I took from sys.object and run this string as my sample to get all dependencies, load all into table. This call to
sql_reference_entities is the only way to get inter database
dependency on column level. So I need stick to this 100$>
--
Select *
From sys.dm_sql_referenced_entities('dbo.v_View_Obs_Table','Object')
--
----update------
This behavior was fixed in SQL Server 2014 SP3 and SQL Server 2016 SP2:
Starting from Microsoft SQL Server 2012, errors raised by
sys.dm_sql_referenced_entities (such as when an object has undergone a
schema change) cannot be caught in a TRY...CATCH Transact-SQL block.
While this behavior is expected in SQL Server 2012 and above, this
improvement introduces a new column that's called is_incomplete to the
Dynamic Management View (DMV).
KB4038418 - Update adds a new column to DMV sys.dm_sql_referenced_entities in SQL Server 2014 and 2016
----update-------
The tldr is that you can't capture these on the server side, and must use a client program in C#, PowerShell or some other client that can process info messages.
That DMV is doing something strange that I don't fully understand. It's generating errors (which a normal UDF is not allowed to do), and those errors do not trigger a TRY/CATCH block or set ##error. EG
create table tempdb.dbo.foo(id int)
go
create view dbo.v_View_Obs_Table
as
select * from tempdb.dbo.foo
go
drop table tempdb.dbo.foo
go
begin try
Select * From sys.dm_sql_referenced_entities('dbo.v_View_Obs_Table','Object')
end try
begin catch
select ERROR_MESSAGE(); --<-- not hit
end catch
However these are real errors, as you can see running this from client code:
using System;
using System.Data.SqlClient;
namespace ConsoleApp6
{
class Program
{
static void Main(string[] args)
{
using (var con = new SqlConnection("Server=.;database=AdventureWorks;integrated security=true"))
{
con.Open();
con.FireInfoMessageEventOnUserErrors = true;
con.InfoMessage += (s, a) =>
{
Console.WriteLine($"{a.Message}");
foreach (SqlError e in a.Errors)
{
Console.WriteLine($"{e.Message} Number:{e.Number} Class:{e.Class} State:{e.State} at {e.Procedure}:{e.LineNumber}");
}
};
var cmd = con.CreateCommand();
cmd.CommandText = "Select * From sys.dm_sql_referenced_entities('dbo.v_View_Obs_Table','Object')";
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read() || (rdr.NextResult() && rdr.Read()))
{
Console.WriteLine(rdr[0]);
}
}
Console.ReadKey();
}
}
}
}
outputs
Invalid object name 'tempdb.dbo.foo'.
Invalid object name 'tempdb.dbo.foo'. Number:208 Class:16 State:3 at v_View_Obs_Table:4
0
The dependencies reported for entity "dbo.v_View_Obs_Table" might not include references to all columns. This is either because the entity references an object that does not exist or because of an error in one or more statements in the entity. Before rerunning the query, ensure that there are no errors in the entity and that all objects referenced by the entity exist.
The dependencies reported for entity "dbo.v_View_Obs_Table" might not include references to all columns. This is either because the entity references an object that does not exist or because of an error in one or more statements in the entity. Before rerunning the query, ensure that there are no errors in the entity and that all objects referenced by the entity exist. Number:2020 Class:16 State:1 at :1

Linq to sql testing stored procedures - call to procedure, verify and rollback in one transaction

I'm trying to use linq to sql for integration testing of stored procedures. I'm trying to call an updating stored procedure and after that retrieving the updated row from db to verify the change. All this should happen in one transaction so that I can rollback the transaction after the verification.
The code fails in assert, because the the row I retrieved does not seem to be updated. I know that my SP works when called from ordinary code. Is it even possible see the updated row in same transaction?
I'm using Sql Server 2008 and used sqlmetal.exe to create linq-to-sql mapping.
I've tried many different things, and right now my code looks following:
DbTransaction transaction = null;
try
{
var context =
new DbConnection(
ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
context.Connection.Open();
transaction = context.Connection.BeginTransaction();
context.Transaction = transaction;
const string newUserName= "TestUserName";
context.SpUpdateUserName(136049 , newUserName);
context.SubmitChanges();
// select to verify
var user=
(from d in context.Users where d.NUserId == 136049 select d).First();
Assert.IsTrue(user.UserName == newUserName);
}
finally
{
if (transaction != null) transaction.Rollback();
}
I believe you are coming acress a stale datacontext issue.
Your update is done through a stored procedure so your context does not "see" the changes and has no way to update the Users.
If you use a new datacontext to do the assert, it usually works well. However, since you are using a transaction you probably have to add the second datacontext to the same transaction.

Resources