Convert a table record to jsonb and assign to a variable - jsonb

I am facing an error in converting a table record to jsonb and then assign it to a variable. I am getting the follwing error. I also tried with to_jsonb function and it too gave the same error.
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
Following is the code I am using. Table users has a lot of columns about 100. I hope this does not matter.
do
$$
declare
json_elements jsonb;
begin
select json_elements = row_to_json(t)::jsonb from users t limit 1;
select json_elements;
end;
$$
Note: I am using postgres 9.5 version.

I changed the code as follows and it worked.
do
$$
declare
json_elements jsonb;
begin
select row_to_json(t)::jsonb into json_elements from users t limit 1;
raise notice '%s' json_elements;
end;
$$
The error was in the select statements. I am from SQL server background and i wanted to see the value by using the select. So I changed the first select to select into and the replaced the second one with raise notice. it started working.

Related

Oracle SQL: PLS-00049 Bad Bind variable when selecting NEXTVAL from a sequence

So, I'm trying to use JDBC to access my Oracle DB, and I found out that, for the functions in JDBC to return results correctly, I need to make an iterator for my tables. So, after searching around and figuring out what that means, I came up with the following code snippet to get that done:
--create a sequence for use in the trigger
CREATE SEQUENCE accounts_seq;
--make the trigger on insert or update
CREATE OR REPLACE TRIGGER account_pk_trig
BEFORE INSERT OR UPDATE ON accounts
FOR EACH ROW
BEGIN
IF inserting THEN
SELECT : accounts_seq.NEXTVAL INTO : NEW.accountnumber FROM dual;
ELSE IF updating THEN
SELECT : OLD.accountnumber INTO : NEW.accountnumber FROM dual;
END IF;
END IF;
END;
/
And, not only is Oracle SQL Developer putting the dreaded red underline of doom in the space after the semicolon put after end, but also on the forward slash to end the code block. As far as I've seen, this appears to be correct to the Oracle SQL examples of trigger definitions that I've seen... and I'm not sure if this is due to the Oracle SQL Developer not recognizing NEXTVAL as a keyword... because it isn't highlighted like the others are.
After some fiddling around, I realized that the "ELSE IF" opened a new IF statement that I didn't close. But, still getting Bad Bind variable error.
For those of you who would want to make sure that the "accountnumber" field exists in the table "accounts", here's my definition for the "accounts" table.
CREATE TABLE accounts (
accountnumber NUMBER NOT NULL,
routingnumber NUMBER NOT NULL,
acctype VARCHAR2(20),
balance NUMBER (*,2),
ownerid NUMBER,
CONSTRAINT accountnumber_pk PRIMARY KEY (accountnumber)
);
You have two major errors in your PL/SQL code:
First the select : is wrong. You can't just throw in a colon like that. The NEW and OLD records do need a colon, but without a space. :new, not : new.
To store the result of a query in a variable you need:
select accounts_seq.NEXTVAL
INTO :NEW.accountnumber
FROM dual;
But you don't need a SELECT for that, you can use a simple variable assignment:
:NEW.accountnumber := accounts_seq.NEXTVAL;
You also have two END IFs although you only have a single IF
And as documented in the manual it needs to be ELSIF, not ELSE IF
Putting all that together, your trigger should be:
CREATE OR REPLACE TRIGGER account_pk_trig
BEFORE INSERT OR UPDATE ON accounts
FOR EACH ROW
BEGIN
IF inserting THEN
:NEW.accountnumber := accounts_seq.NEXTVAL;
ELSIF updating THEN
:NEW.accountnumber := :OLD.accountnumber;
END IF;
END;
/
As the trigger is declared as BEFORE INSERT OR UPDATE the ELSIF is actually useless, because it can only be insert or updating nothing else. So instead of ELSIF updating THEN you could simply write ELSE

Problems inserting data into Oracle table with sequence column via SSIS

I am doing data insert into a table in Oracle which is having a sequence set to it in one of the columns say Id column. I would like to know how to do data loads into such tables.
I followed the below link -
It's possible to use OleDbConnections with the Script Component?
and tried to create a function to get the .nextval from the Oracle table but I am getting the following error -
Error while trying to retrieve text for error ORA-01019
I realized that manually setting the value via the package i.e. by using the Script task to enumerate the values but is not incrementing the sequence and that is causing the problem. How do we deal with it? Any links that can help me solve it?
I am using SSIS-2014 but I am not able to tag it as I don't due to paucity of reputation points.
I created a workaround to cater to this problem. I have created staging tables of the destination without the column that takes the Sequence Id. After the data gets inserted, I am then calling SQL statement to get the data into the main tables from staging table and using the .nextval function. Finally truncating/dropping the table depending on the need. It would still be interesting to know how this same thing can be handled via script rather having this workaround.
For instance something like below -
insert into table_main
select table_main_sequence_name.nextval
,*
from (
select *
from table_stg
)
ORA-01019 may be related to fact you have multiple Oracle clients installed. Please check ORACLE_HOME variable if it contains only one client.
One workaround I'm thinking about is creating two procedures for handling sequence. One to get value you start with:
create or replace function get_first from seq as return number
seqid number;
begin
select seq_name.nexval into seqid from dual;
return seqid;
end;
/
Then do your incrementation in script. And after that call second procedure to increment sequence:
create or replace procedure setseq(val number) as
begin
execute immediate 'ALTER SEQUENCE seq_name INCREMENT BY ' || val;
end;
/
This is not good approach but maybe it will solve your problem

ORA-0675:package or function ORG_SPGETTYPE is in an invalid state

PROCEDURE ORG_spGetType
(
v_TypeId IN NUMBER DEFAULT NULL
)
AS
BEGIN
SELECT *
FROM ORG_Type
WHERE TypeId = v_TypeId ;
END;
While Running above proceedure in oracle10g usinq eclipse platform sql editor getting error like "ORA-0675:package or function ORG_SPGETTYPE is in an invalid state"
That's not much of a surprise; that procedure is invalid. When compiling a procedure or any other PL/SQL block you should check whether it's compiled correctly.
If you're compiling on the command line, i.e. in SQL*Plus you can use the SHOW command and use the ERRORS variable, which:
displays the line and column number of the error (LINE/COL) as well as the error itself (ERROR).
After you've compiled the procedure type the following:
show errors
Alternatively, you can use the USER_ERRORS system view which will show you a list of all errors, which the schema you're in can see.
select *
from user_errors
where name = 'ORG_SPGETTYPE'
The actual reason for your error is that you cannot simply SELECT in PL/SQL. If you do you're not giving PL/SQL the ability to use the results of your SELECT statement in any way and so it won't allow you to do so. If you're selecting something you need to do something with it; what that something is is up to you.
There are numerous ways of doing this but let's say the table ORG_TYPE is unique on the column TYPEID and you want to return one column as an OUT parameter. Your procedure would then look like this:
create or replace procedure org_spgettype (
P_typeid in org_type.type_id%type
, P_some_column out org_type.some_column%type
) is
begin
select some_column into P_some_column
from org_type
where typeid = P_typeid;
end;
/
show errors
Please note a number of things:
There doesn't seem to be any need for the DEFAULT NULL if this is your primary key; it can't be NULL so you don't want to allow this possibility.
I've declared your parameters as the type of the column; this enables you to change the column without having to recode everything.
There is so much more to explain about all of this (exceptions for a start) so I would highly recommend taking some basic tutorials first or asking a colleague/friend for help.
You would have a 'compiled with warnings' message when creating the procedure. You can query the user_errors view to see what problems are reported for your peocedure. You will see something like 'PLS-00428: an INTO clause is expected in this SELECT statement', because you are not selecting into something.
The documentation shows how to do that. You need to declare variables to select into. In this case you could declare a rowtype variable:
CREATE OR REPLACE PROCEDURE ORG_spGetType (v_TypeId IN NUMBER DEFAULT NULL) AS
l_org_type org_type%rowtype;
BEGIN
SELECT *
INTO l_org_type
FROM ORG_Type
WHERE TypeId = v_TypeId ;
-- do something with l_org_type
END;
/
Note that this can get a no_data_found exception if there are no matching rows, or too_many_rows if there are multiple matches for the passed ID.
But it isn't clear what you're planning to do with the retrieved data. This currently does nothing at all with it, it's just selected and then forgotten. The name of the procedure suggests you want to return all or part of the data from the table to the caller. If it's only one field value then this should probably be a function rather than a procedure. Or you could add out parameters to put the values into (as Ben shows), or return a refcursor. Depends what you need.
The default null, however, maybe suggests you sometimes expect more than one result, maybe the whole table if no value is passed - though your where clause won't find anything if v_typeid is null.

Get the Affected Row from PL-SQL

I am using ODP.Net and run the PL/SQL Command to merge the table in the Oracle 10G database.
My command is as follow:
MERGE INTO TestTable t
USING (SELECT 2911 AS AR_ID FROM dual) s
ON (t.AR_ID = s.AR_ID)
WHEN MATCHED THEN
UPDATE SET t.AR_VIUAL_IMPAIRMENT = 1
WHEN NOT MATCHED THEN
INSERT (AR_S_REF)
VALUES ('abcdef');
SELECT sql%ROWCOUNT FROM dual;
The Merge command runs successfully and update/insert as I want. The problem is I want to know how many records are updated.
When I run the above statement, "ORA-00911: invalid character error".
Please advise me how I could get the affected rows back. Thanks million.
You're mixing up a few things: a MERGE statement is a plain SQL command while PL/SQL code is always delimited by BEGIN/END (and optional DECLARE). Furthermore, SQL%ROWCOUNT is a PL/SQL variable that cannot occur outside of PL/SQL.
And I don't quite understand whether you ran the MERGE and the SELECT statement with two separate or a common ODP.NET call.
Anyway, the solution is straightfowrad with ODP.NET: Execute the MERGE command with OracleCommand.ExecuteNonQuery(). This method returns the number of affected rows.
One thing you could do is put your code in a PLSQL function that returns %ROWCOUNT.
Then call this function from ODP.net setting the command type to stored procedure and using the ExecuteLiteral method which is going to return you the row count as an object instance you can cast as an int.
It is not possible to return just the "updated" row count.
(as already mentioned the row count is the number of affected (inserted and updated) rows)
there is a good discusion on ask tom: http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:122741200346595110

Debugging dynamic sql + dynamic tables in MS SQL Server 2008

I have a messy stored procedure which uses dynamic sql.
I can debug it in runtime by adding print #sql; where #sql; is the string containing the dynamic SQL, right before I call execute (#sql);.
Now, the multi-page stored procedure also creates dynamic tables and uses them in a query. I want to print those tables to the console right before I do an execute, so that I know exactly what the query is trying to do.
However, the SQL Server 08 does not like that. When I try:
print #temp_table; and try to compile the S.P. I get this error:
The name "#temp_table" is not permitted in this context. Valid expressions are constants, constant expressions, and (in some contexts) variables. Column names are not permitted.
Please help.
EDIT:
I am a noob when it comes to SQL. However, the following statement: select * from #tbl; does not print anything to the console when it is run non-interactively; the print statement works though.
The following statement has incorrect syntax: print select * from #tbl;. Is there a way for me to redirect the output of select to a file, if stdout is not an option?
Thanks.
When we use dynamic SQl we start by having a debug input variable in the sp (make it the last one and give it a default value of 0 (to indicate not in debug mode that way it won't break existing code calling the proc).
Now when you run it in debug mode, you print instead of execute or you print and execute but you always rollback at the end. If you need to see the data at various stages, the best thing to do is the second. Then before you rollback you put the data you want to see into a a table varaiable (This is important it can't be a temp table). after the rollback, select from the table variable (which did not go out of scope with the rollback) and run your print tstatments to see the queries which were run.
Debugging this way the only way you'll get output is
select * from #temp_table;
Alternatively, look into the debugging features built into SQL Server Management Studio. For example, this web page may help you
SQL Server Performance . com
You can print Variables, but not tables. You can, however, SELECT from the #table.
Now, if the table is created, filled up and modified in a single statement that is executed, then you can view the state of the table as it was before being modified, but the data will have changed since.
of course, as soon as the dynamic sql finishes, the #table is no longer available so you're stuck!
To counter that, you can insert into a ##Table (note the double hash marks) in your dynamic SQL along with the #table and then query that ##table at the end of execution of the dynamic sql.
for as much as I hate cursors, give this a try:
SET NOCOUNT ON
CREATE TABLE #TempTable1
(ColumnInt int
,ColumnVarchar varchar(50)
,ColumnDatetime datetime
)
INSERT INTO #TempTable1 VALUES (1,'A',GETDATE())
INSERT INTO #TempTable1 VALUES (12345,'abcdefghijklmnop','1/1/2010')
INSERT INTO #TempTable1 VALUES (null,null,null)
INSERT INTO #TempTable1 VALUES (445454,null,getdate())
SET NOCOUNT OFF
DECLARE #F_ColumnInt int
,#F_ColumnVarchar varchar(50)
,#F_ColumnDatetime datetime
DECLARE CursorTempTable1 CURSOR FOR
SELECT
ColumnInt, ColumnVarchar, ColumnDatetime
FROM #TempTable1
ORDER BY ColumnInt
FOR READ ONLY
--populate and allocate resources to the cursor
OPEN CursorTempTable1
PRINT '#TempTable1 contents:'
PRINT ' '+REPLICATE('-',20)
+' '+REPLICATE('-',50)
+' '+REPLICATE('-',23)
--process each row
WHILE 1=1
BEGIN
FETCH NEXT FROM CursorTempTable1
INTO #F_ColumnInt, #F_ColumnVarchar, #F_ColumnDatetime
--finished fetching all rows?
IF ##FETCH_STATUS <> 0
BEGIN --YES, all done fetching
--exith the loop
BREAK
END --IF finished fetching
PRINT ' '+RIGHT( REPLICATE(' ',20) + COALESCE(CONVERT(varchar(20),#F_ColumnInt),'null') ,20)
+' '+LEFT( COALESCE(#F_ColumnVarchar,'null') + REPLICATE(' ',50) ,50)
+' '+LEFT( COALESCE(CONVERT(char(23),#F_ColumnDatetime,121),'null') + REPLICATE(' ',23) ,23)
END --WHILE
--close and free the cursor's resources
CLOSE CursorTempTable1
DEALLOCATE CursorTempTable1
OUTPUT:
#TempTable1 contents:
-------------------- -------------------------------------------------- -----------------------
null null null
1 A 2010-03-18 13:28:24.260
12345 abcdefghijklmnop 2010-01-01 00:00:00.000
445454 null 2010-03-18 13:28:24.260
If I knew that your temp table had a PK, I'd give a cursor free loop example.

Resources