Background: I am mapping Sybase stored procedure return values to java objects using Spring.
For example I map a Sybase datatype of varchar as a String type in Java, and a Sybase datatype of int as an int type in Java, etc.
I have come across the following code in one of the stored procedures:
SELECT DISTINCT
A.Col1 AS val1,
A.Col2 AS val2,
NULL AS someVal,
A.col3 AS val3,
...
A.col9 AS val9
FROM #SomeTable A
ORDER BY Col2, Col3
I have 2 related questions:
What does Null mean in this scenario? I am confused as to what is happening here.
I am able to determine the data type of Col1, Col2, etc. of course by looking at the table definition of Table A defined earlier in the stored procedure. Thus I know what datatype I can define in my Java object for val1, val2, etc.. But what about "someVal"? What datatype mapping am I supposed to perform for this Null value?
I am fairly inexperienced in SQL. Perhaps the answer is much simpler than I realize.
This creates a column with NULL values in all rows. This trick is useful when
The reader of your query results expects a column someVal to be there, treating situations when this column is missing as errors, or
Your query is part of a UNION ALL query inside a GROUP BY query, with other queries filling in values for NULLs.
Here is an example of the later situation:
SELECT -- This query flattens the results of the two sub-queries
document_id
, MIN(approval_date) as approval_date
, MIN(availability_date) as availability_date
FROM (
SELECT -- This subquery supplies approval_date
document_id
, MAX(approval_date) AS approval_date
, NULL AS availability_date
FROM document_approvals
GROUP BY document_id
UNION ALL
SELECT -- This subquery supplies availability_date
document_id
, NULL AS approval_date
, MAX(availability_date) AS availability_date
FROM document_approvals
GROUP BY document_id
)
GROUP BY document_id
You will have a column called someVal with NULL as the value for each row.
With a ResultSet, you can use getString(int) or getString(String) which states
Returns: the column value; if the value is SQL NULL, the value
returned is null
You can choose any reference type you want, including Void, to map this column. Or don't use any, ie. don't map it. Depends on your requirement.
Related
I'm trying to make a blog system of sort and I ran into a slight problem.
Simply put, there's 3 columns in my article table:
id SERIAL,
category VARCHAR FK,
category_id INT
id column is obviously the PK and it is used as a global identifier for all articles.
category column is well .. category.
category_id is used as a UNIQUE ID within a category so currently there is a UNIQUE(category, category_id) constraint in place.
However, I also want for category_id to auto-increment.
I want it so that every time I execute a query like
INSERT INTO article(category) VALUES ('stackoverflow');
I want the category_id column to be automatically be filled according to the latest category_id of the 'stackoverflow' category.
Achieving this in my logic code is quite easy. I just select latest num and insert +1 of that but that involves two separate queries.
I am looking for a SQL solution that can do all this in one query.
This has been asked many times and the general idea is bound to fail in a multi-user environment - and a blog system sounds like exactly such a case.
So the best answer is: Don't. Consider a different approach.
Drop the column category_id completely from your table - it does not store any information the other two columns (id, category) wouldn't store already.
Your id is a serial column and already auto-increments in a reliable fashion.
Auto increment SQL function
If you need some kind of category_id without gaps per category, generate it on the fly with row_number():
Serial numbers per group of rows for compound key
Concept
There are at least several ways to approach this. First one that comes to my mind:
Assign a value for category_id column inside a trigger executed for each row, by overwriting the input value from INSERT statement.
Action
Here's the SQL Fiddle to see the code in action
For a simple test, I'm creating article table holding categories and their id's that should be unique for each category. I have omitted constraint creation - that's not relevant to present the point.
create table article ( id serial, category varchar, category_id int )
Inserting some values for two distinct categories using generate_series() function to have an auto-increment already in place.
insert into article(category, category_id)
select 'stackoverflow', i from generate_series(1,1) i
union all
select 'stackexchange', i from generate_series(1,3) i
Creating a trigger function, that would select MAX(category_id) and increment its value by 1 for a category we're inserting a row with and then overwrite the value right before moving on with the actual INSERT to table (BEFORE INSERT trigger takes care of that).
CREATE OR REPLACE FUNCTION category_increment()
RETURNS trigger
LANGUAGE plpgsql
AS
$$
DECLARE
v_category_inc int := 0;
BEGIN
SELECT MAX(category_id) + 1 INTO v_category_inc FROM article WHERE category = NEW.category;
IF v_category_inc is null THEN
NEW.category_id := 1;
ELSE
NEW.category_id := v_category_inc;
END IF;
RETURN NEW;
END;
$$
Using the function as a trigger.
CREATE TRIGGER trg_category_increment
BEFORE INSERT ON article
FOR EACH ROW EXECUTE PROCEDURE category_increment()
Inserting some more values (post trigger appliance) for already existing categories and non-existing ones.
INSERT INTO article(category) VALUES
('stackoverflow'),
('stackexchange'),
('nonexisting');
Query used to select data:
select category, category_id From article order by 1,2
Result for initial inserts:
category category_id
stackexchange 1
stackexchange 2
stackexchange 3
stackoverflow 1
Result after final inserts:
category category_id
nonexisting 1
stackexchange 1
stackexchange 2
stackexchange 3
stackexchange 4
stackoverflow 1
stackoverflow 2
Postgresql uses sequences to achieve this; it's a different approach from what you are used to in MySQL. Take a look at http://www.postgresql.org/docs/current/static/sql-createsequence.html for complete reference.
Basically you create a sequence (a database object) by:
CREATE SEQUENCE serials;
And then when you want to add to your table you will have:
INSERT INTO mytable (name, id) VALUES ('The Name', NEXTVAL('serials')
i have stuck :)
does anyone know how query postgresql in jsonb
i have table USER
INT id,
Varchar name,
jsonb categoryId
the example data in categoryId field like this = [1,2,3,4,5]
I have tried this query which works:
select *
from user where categoryId #> '2'::jsonb ;
but how to query with multiple params like
select *
from user
where categoryId #> '1,3,4'::jsonb
and i will implement this to hibernate jpa/jpql-predicate, but i want to know native query first
Thankyou so much
In SQL you can use the ?| operator for this
select *
from "user"
where categoryid ?| array['1','3','4'];
That will return rows where at least one of the values is contained in the JSON array. If you want to find those that contain all values, use the ?& operator instead.
To use the #> operator you would need to use a JSON array on the right hand side:
select *
from "user"
where categoryid #> '[1,3,4]'::jsonb
Note that user is a reserved keyword. You will have to enclose it in double quotes every time you want to refer to the table. I would highly recommend to find a different table name.
I am a beginner PLSQL user, and I have what might be a rather simple question.
I have created the following SQL Function, which returns the created date of the process whose corporate ID matches the corporate ID that I have given it. I have this connected to my JDBC, and it returns values just fine.
However, I just realized I overlooked an important issue--it's entirely possible that more than one process will have a corporate ID that matches the ID value I've inputted, and in cases like that I will need to be able to access all of the created date values where the IDs return a match.
CREATE OR REPLACE FUNCTION FUNCTION_1(
c_id IN INT)
RETURN INT
AS
p_date process.date_created%TYPE;
BEGIN
SELECT process.date_created
FROM PROCESS
WHERE process.corporate_id = c_id
ORDER BY process.corporate_id;
RETURN p_id;
END FUNCTION_1;
/
Is there a way that I can modify my function to return multiple rows from the same column, and then call that function to return some sort of array using JDBC? Or, if that isn't possible, is there a way I can return what I need using PLSQL procedures or just plain SQL combined with JDBC? I've looked through other questions here, but none seemed to be about quite what I need to know.
Thanks to anyone who can help!
you need make some changes in your function. on java side it will be simple select
you need change type of your function from int to collection
read about the table functions here Table Functions
user oracle table() function to convert result of your function to table
it let you use your function in queries. read more about the syntax here: Table Collections: Examples
here the example how to call your function from java:
select t.column_value as process_id
from table(FUNCTION_1(1)) t
--result
PROCESS_ID
1 1
2 2
--we need create new type - table of integers
CREATE OR REPLACE TYPE t_process_ids IS TABLE OF int;
--and make changes in function
CREATE OR REPLACE FUNCTION FUNCTION_1(
c_id IN INT)
RETURN t_process_ids
AS
l_ids t_process_ids := t_process_ids();
BEGIN
--here I populated result of select into the local variables
SELECT process.id
bulk collect into l_ids
FROM PROCESS
WHERE process.corporate_id = c_id
ORDER BY process.corporate_id;
--return the local var
return l_ids;
END FUNCTION_1;
--the script that I used for testing
create table process(id int, corporate_id int, date_created date);
insert into process values(1, 1, sysdate);
insert into process values(2, 1, sysdate);
insert into process values(3, 2, sysdate);
I have two tables that I want to join using hibernate. The join column, as represented in my model is a String (its a varchar(10) in my database). When I run the HQL query, what I see is the following error, "conversion failed when converting the varchar value 'AS00' to data type int. "AS500" is the first value of join column in the first row.
I do not know why hibernate is doing this. My join column is not an int. I have checked both models corresponding to my tables and they are both defined as Strings. Is there some kind of restriction on the data types that can be used for join columns?
Please post both your model and the hql query.
If I had to take a guess (and that's all any of us can do without specifics), I would say that your hql query does not use .setParameter and it does not have single quotes around the string value in your query... so it is trying to implicitly convert the value to int.
Example that would cause this error:
Query query = session.createQuery("from Person where name = bob");
I have a situation where i have to count number of strings of same type in one column of a table, for eg. a column would be having values such as A=absent P=present
A A A P P P P P P P A
So i need to count all the strings of same type, like P i.e Present that means query should give count result 7.
What can be idol query for this?
I think this is the simplest Query that I can think of in terms of SQL Select count(*) from table where attendence='P'
Update:
Ensure to use parameterized format of prepared statement in your Java code to prevent SQL Injection.
SELECT attendance, COUNT(*)
FROM Roster
GROUP BY attendance;
Will give you the count of each value in the column. So, for a table having 4 A values and 7 P values, the query will return
attendance | COUNT(*)
___________|_________
|
A | 4
P | 7
Aside: Since your table has repetitive values in its attendance column, you should consider pulling all possible values for attendance out into their own "enumeration" of sorts. SQL doesn't offer enumerations, but there are a few ways to achieve a similar effect.
One method is to create a look up table that contains an ID column (can be an auto-increment), and the values that you want for attendance. Then, in your Roster table, use a foreign key to reference the ID of the correct value.
To save yourself time in the future, you can create a View which uses the attendance values rather than the IDs.
You can read up on Database Normalization if you're interested in improving your database's design.