For XYZ reason I need a query to explicitly fail (return error code to connection) if some condition is met (on Snowflake).
Can someone recommend an approach?
Some illustration in pseudo-code:
IF 0= ( SELECT COUNT(*) FROM XYZ) THEN FAIL
I like Simeon's approach, but you may want a custom error message if this is running in a long script. Throwing an error in a JavaScript UDF will allow custom (if untidy) error messages:
create or replace function RAISE_ERROR(MESSAGE string)
returns string
language javascript
as
$$
throw "-->" + MESSAGE + "<--";
$$;
select
case (select count(*) from XYZ)
when 0 then raise_error('My custom error.')
else 'There are rows in the table'
end
;
If there are no rows in XYZ, it will generate an error message that reads:
JavaScript execution error: Uncaught --> My custom error <--. in RAISE_ERROR at '
throw MESSAGE;' position 4 stackstrace: RAISE_ERROR line: 2
It's not the tidiest of error messages, but it will allow you to embed a custom error message if you need help identifying the error. The arrows should help direct people to the real error message thrown in the stack.
SELECT IFF(true, 1::number, (1/0)::number);
then:
IFF(TRUE, 1::NUMBER, (1/0)::NUMBER)
1
where-as
SELECT IFF(false, 1::number, (1/0)::number);
gives:
Division by zero
Related
While using the code able I'm getting an error message as below and also I'm getting the output table.
input(put(serv_to_DT_KEY,8.),yymmdd8.)
between datepart(D.throughdate)
and datepart(intnx('day',d.throughdate,31))
Error: INPUT function reported 'ERROR: Invalid date value' while processing WHERE clause.
ERROR: Limit set by ERRORS= option reached. Further errors for this INPUT function will not be printed.
Could you please help
It's not a true error, exactly; it's a data error, which SAS will let by. What it's saying is the value in serv_to_DT_KEY is not a valid yymmdd8 for some records. (The rest of the message, about "limit set by ...", is just SAS saying it's only going to tell you about 20 or so individual data errors instead of showing you every single one, so your log isn't hopeless.)
To fix this you have several options:
If there is a data issue [ie, all rows should have a valid date], then fix that.
If it's okay that some rows don't have a valid date (for example, they might have a missing), you can use the ?? modifier in the informat in input to tell it to ignore these.
Like this:
input(put(serv_to_DT_KEY,8.),?yymmdd8.)
between datepart(D.throughdate)
and datepart(intnx('day',d.throughdate,31))
DO $$
BEGIN
-- Check to make sure that event starts after users created
IF EXISTS (
SELECT users.id
FROM event
INNER JOIN users ON event.user_id::INT = users.id
WHERE event.start > users.created
)
THEN
RAISE NOTICE 'SUCCESSFUL %', now();
ELSE
RAISE EXCEPTION 'ERROR on % - All Event start timestamps must be created after users are created',now();
END IF;
END $$;
This exception is to check for timestamps and works well. But I want to add a similar condition and at-least 3 more exception conditions. I want to now return the exceptions at the end. I do-not want process to stop if first check fails. I want all the failed tests to be raised all at once in the end. How do I do that ? I read about stacked diagnostics bu dontt know if its the right approach or should I just use IF-else if ?
It is in the nature of an exception to interrupt processing, so you cannot simply use exceptions for that.
You could collect all exceptions in a (temporary?) table and communicate them to the client in the end, or concatenate them to a single large exception.
You could also emit the individual messages as NOTICE and throw an exception at the end.
I'm trying to setup some useful error handling in a program that used ODBC. According to documentation if SQLExecDirect returns SQL_ERROR I should be able to call SQLGetDiagRec to get SQL_STATE and possibly some messages, but in my tests when I call SQLGetDiagRec right after getting an error from SQLExecDirect I get SQL_NO_DATA returned and no information.
Code:
result = SQLExecDirect(hstmt, <SQL Statement>, SQL_NTS);
if(result == SQL_ERROR)
{
SQLSMALLINT msg_len = 0;
SQLCHAR sql_state[6], message[256];
SQLINTEGER native_error = 0;
result = SQLGetDiagRec(SQL_HANDLE_DBC, hDbc, 1, sql_state, &native_error, message, countof(message), &msg_len);
// Here 'result' is SQL_NO_DATA
....
}
It works in other cases, just not for SQLExecDirect for some reason. I'm also aware that one should cycle through the SQLGetDiagRec results, but if the very first one returns SQL_NO_DATA, according to documentation it means that there are no further ones.
The specific error that I was testing it with was requesting a non-existent table.
Is there anything else that I need to do in order obtain at least an error code, or does the diagnostic not work for errors that result from incorrect SQL requests?
When you call SQLGetDiagRec, pass SQL_HANDLE_STMT and your statement handle (hstmt in your example). That should return errors associated with that specific statement.
Is it possible to throw a Lua error from a function to be handled by the script calling the function?
For example the following will throw an error at indicated comment
local function aSimpleFunction(...)
string.format(...) -- Error is indicated to be here
end
aSimpleFunction("An example function: %i",nil)
But what I would rather do is catch the error and throw out a custom error by the function caller
local function aSimpleFunction(...)
if pcall(function(...)
string.format(...)
end) == false then
-- I want to throw a custom error to whatever is making the call to this function
end
end
aSimpleFunction("An example function: %i",nil) -- Want the error to start unwinding here
The intention being that in my actual use cases my functions would be more complicated and I would like to provide more meaningful error messages
The stack level of an error can be specified when throwing a new error
error("Error Message") -- Throws at the current stack
error("Error Message",2) -- Throws to the caller
error("Error Message",3) -- Throws to the caller after that
Usually, error adds some information about the error position at the beginning of the message. The level argument specifies how to get the error position. With level 1 (the default), the error position is where the error function was called. Level 2 points the error to where the function that called error was called; and so on. Passing a level 0 avoids the addition of error position information to the message.
Using the example given in the question
local function aSimpleFunction(...)
if pcall(function(...)
string.format(...)
end) == false then
error("Function cannot format text",2)
end
end
aSimpleFunction("An example function: %i",nil) --Error appears here
Use the error function.
error("something went wrong!")
Catching an error is as simple as using pcall
My_Error()
--Error Somehow
end
local success,err = pcall(My_Error)
if not success then
error(err)
end
Undoubtedly you're asking how this works. Well pcall runs a function in a protected thread (protected-call) and returns a bool, if it ran successfully, and a value (what it returned/the error).
Also don't think this means arguments to the function are impossible, simply pass them to pcall as well:
My_Error(x)
print(x)
--Error Somehow
end
local success,err = pcall(My_Error, "hi")
if not success then
error(err)
end
For more error handling control, see http://www.lua.org/manual/5.3/manual.html#2.3 and http://wiki.roblox.com/index.php?title=Function_dump/Basic_functions#xpcall
Hi I have problem to catch the error in merge statement.
The merge statement will get the following error when run in SQL Plus:
ORA-00932: inconsistent datatypes: expected DATE got NUMBER
When I execute the statement with ExecuteNonQuery in Vb.net will not get any exception.
Is there any way to catch that error in Vb.net without using log errors in merge statement?
EDIT:
Try
Dim count as Interger=0
Dim cmd As New OleDb.OleDbCommand(strSQL)
count = cmd .ExecuteNonQuery()
Catch ex as Exception
... Respond ...
End Try
Sample Merge Statement with error:
MERGE INTO TABLE_A a USING
(
SELECT ID,SUM(AMOUNT) AMOUNT
FROM TABLE_B b
GROUP BY ID
) b
ON ( b.ID=a.ID )
WHEN MATCHED THEN
UPDATE SET a.AMOUNT=a.AMOUNT+b.AMOUNT
WHEN NOT MATCHED THEN
INSERT (ID, DT, AMOUNT) VALUES (b.ID, 0, b.AMOUNT);
The SQL Plus will get error at the insert but Vb.net can not catch.
The data type for field DT is DATE.
EDIT 3:
My bad - in that case, I think you'll have to subscribe to oleDbConnection.InfoMessage event and check for applicable SQL-00932 messages after the MERGE command. I don't see any equivalent property to FireInfoMessageEventOnUserErrors in OLE-DB (which, again, seems totally backwards...).
EDIT 2:
It appears there's a default threshold that will cause vb.net to ignore certain SQL exceptions (can't fathom the rationale behind such a decision). Regardless, I think if you do the following, you should see the exception raised.
cmd.FireInfoMessageEventOnUserErrors = true;
End EDIT2
EDIT: I just read the problem a bit closer. If the vb.net execution is not throwing any exception at all, that would indicate that you're not running the exact same statement in both. My initial guess is that you're passing a date parameter that is passing SQL Plus string variable incorrectly as 01/01/2015 (which is 1 divided by 1 divided by 2015) and vb.net variable correctly as '01/01/2015' (that is, as a string with quotation marks).
End EDIT
I have no idea what you mean by "using log errors in merge statement", but it sounds like you just need the syntax for using the vb.net try-catch syntax to catch and act on Oracle errors.
From here: http://www.tek-tips.com/viewthread.cfm?qid=467119
Pertinent code snippet:
Try
... Sql here ...
Catch ex as OleDbException
... Respond to error here ...
End Try