Create view with except condition - sql

Example i want to create a view name TEST
which i already created a view before that
View name : customer
Inside customer View:
//CUSTOMER
NAME ID ADDRESS AGE SEX TELNO EMAIL
-----------------------------------------------------------------------
CHRIS 1 12321312 21 F 646885 ascs#gmail
JOHN 2 SADASDSA 23 M 5452131 asd#gmail
MAY 3 LKJLKJLKJ 32 F 645643 cxz#gmail
So i want to create a view name TEST that will store all column inside CUSTOMER but EXCEPT TELNO EMAIL.
so i used this query:
CREATE VIEW TEST AS
SELECT * FROM CUSTOMER
EXCEPT
SELECT TELNO,EMAIL FROM CUSTOMER;
But i fail to work, got errors come out. SQL command not properly end and point to EXCEPT, what's wrong?

You have to list all the columns that you want explicitly:
CREATE VIEW TEST AS
SELECT NAME, ID, ADDRESS, AGE, SEX
FROM CUSTOMER;
There is no way to exclude some columns from a * list.
EXCEPT is an operator in SQL Server. The equivalent in Oracle is MINUS. However, this works at the row level, not at the column level.
If you want to get all the columns in the table, except for those two, you can use all_tab_columns:
select column_name
from all_tab_columns
where lower(table_name) = 'customer' and
lower(column_name) not in ('telno', 'email');
You can then paste them into the select clause.

Related

Execute same query multiple times with different parameter postgressql

I don't know how to easily explain what i need to do but i'll try.
Lets say i have a user table with 5 users.
id name
1 Steve
2 Pat
3 Robin
4 Carl
5 Sarah
instead of just do a select * from users i need to do this different and more difficult.
I need to build a query that for each row in users table runs a query with a parameter (name) and then gives me the same output as select * from users
I know it's sounds wierd but this is what i actually needs to do..
So what i want to happen is this:
I need to loop thru the users table to find out how many rows there is. (5)
-That's the amount of times I want to execute the query.
For each execution of the Query i need to change name in the where clause. First execution = Steve, second = Pat and so on.
In the end I want just one output with everything together so I need to union the result.
If i would this manually it would look like this:
Select id, name from users where name = 'Steve'
union all
Select id, name from users where name = 'Pat'
union all
Select id, name from users where name = 'Robin'
union all
Select id, name from users where name = 'Carl'
union all
Select id, name from users where name = 'Sarah'
In my real case i need separate queries so a in ('Steve', 'Pat') or a solution like that won't work.
I hope you understand what im looking for, and if you have any question please ask. Im using postgres v.10
This should work as you intend to.
DO $$
DECLARE
var_req TEXT;
rec_key record;
cur_key CURSOR FOR SELECT distinct name from users;
BEGIN
open cur_key;
loop
fetch cur_key into rec_key;
EXIT WHEN NOT FOUND;
var_req := '
insert into your_output_table
select id, name from users
where name = '''||rec_key.name||'''
;
';
execute var_req;
end loop;
close cur_key;
END $$;

How to execute a select with a WHERE using a not-always-existing column

Simple example: I have some (nearly) identical tables with personal data (age, name, weight, ...)
Now I have a simple, but long SELECT to find missing data:
Select ID
from personal_data_a
where
born is null
or age < 1
or weight > 500
or (name is 'John' and surname is 'Doe')
Now the problem is:
I have some personal_data tables where the column "surname" does not exit, but I want to use the same SQL-statement for all of them. So I have to check (inside the WHERE clause) that the last OR-condition is only used "IF the column surname exists".
Can it be done in a simple way?
You should have all people in the same table.
If you can't do that for some reason, consider creating a view. Something like this:
CREATE OR REPLACE VIEW v_personal_data
AS
SELECT id,
born,
name,
surname,
age,
weight
FROM personal_data_a
UNION ALL
SELECT id,
born,
name,
NULL AS surname, --> this table doesn't contain surname
age,
weight
FROM personal_data_b;
and then
SELECT id
FROM v_personal_data
WHERE born IS NULL
OR age < 1
OR ( name = 'John'
AND ( surname = 'Doe'
OR surname IS NULL))
Can it be done in a simple way?
No, SQL statements work with static columns and the statements will raise an exception if you try to refer to a column that does not exist.
You will either:
need to have a different query for tables with the surname column and those without;
have to check in the data dictionary whether the table has the column or not and then use dynamic SQL to build your query; or
to build a VIEW of the tables which do not have that column and add the column to the view (or add a GENERATED surname column with a NULL value to the tables that are missing it) and use that instead.
While dynamic predicates are usually best handled by the application or by custom PL/SQL objects that use dynamic SQL, you can solve this problem with a single SQL statement using DBMS_XMLGEN, XMLTABLE, and the data dictionary. The following code is not what I would call "simple", but it is simple in the sense that it does not require any schema changes.
--Get the ID column from a PERSONAL table.
--
--#4: Get the IDs from the XMLType.
select id
from
(
--#3: Convert the XML to an XMLType.
select xmltype(personal_xml) personal_xmltype
from
(
--#2: Convert the SQL to XML.
select dbms_xmlgen.getxml(v_sql) personal_xml
from
(
--#1: Use data dictionary to create SQL statement that may or may not include
-- the surname predicate.
select max(replace(replace(
q'[
Select ID
from #TABLE_NAME#
where
born is null
or age < 1
or weight > 500
or (name = 'John' #OPTIONAL_SURNAME_PREDICATE#)
]'
, '#TABLE_NAME#', table_name)
, '#OPTIONAL_SURNAME_PREDICATE#', case when column_name = 'SURNAME' then
'and surname = ''Doe''' else null end)) v_sql
from all_tab_columns
--Change this literal to the desired table.
where table_name = 'PERSONAL_DATA_A'
)
)
where personal_xml is not null
)
cross join xmltable
(
'/ROWSET/ROW'
passing personal_xmltype
columns
id number path 'ID'
);
See this db<>fiddle for a runnable example.

Select data from table with column name and description SQL Server

I have a legacy table with all column named in an old way, the names don't make sense to others, but the table description contains column description, how to can select all data from the table, and combine with the column description?
UPDATED BELOW:
To get the Names and Columns Description
SELECT
COLUMN_NAME AS Name,
COLUMN_TEXT AS Description
FROM
[DB2-LINKED-SERVER].[BD2].QSYS2.SYSCOLUMNS
WHERE
TABLE_NAME = 'ITMHED'
I got:
Name Description
ITMNO Item Number
ITMNM Item Name
.... 800+ rows more
Then I have another query:
SELECT * FROM [DB2-LINKED-SERVER].[BD2].ITMHED
It returned me:
ITMNO ITMNM ...800+ more columns
AB-001 Mountain Bike ....
What I want to get:
Item Number Item Name ...800+ more columns
AB-001 Mountain Bike .....
If I need only 2-3 column, I can manually rename them, but with that many record, I want to make it more readable for users. I need to generate a report from that.
SELECT
COLUMN_NAME AS Name + ' as '+
COLUMN_TEXT AS Description + ','
FROM
[DB2-LINKED-SERVER].[BD2].QSYS2.SYSCOLUMNS
WHERE
TABLE_NAME = 'ITMHED'
Could get the output from that and then insert it into the following:
select (insert the output from above here) from [DB2-LINKED-SERVER].[BD2].ITMHED

Updating table where LIKE has several criteria

I have two tables in PostgreSQL (version 9.3). The first holds id, title and the second holds schdname. I'm trying to create a select statement that will retrieve id and title where the title contains the schdname from the other table. The id, title table can hold several thousand rows. I can do this fine if I use WHERE LIKE for an individual schdname example but there are 40 plus names so this is not practical.
My original query ran like this which I know doesn't work but would show what I'm trying to achieve.
SELECT
id,
title,
dname
FROM
mytable
WHERE
title LIKE (
SELECT
schdname
FROM
schedule
)
This produces an error of more than one row returned by the subquery used as an expresssion. So my question is can this be achieved another way?
Here is one way to do that:
SELECT id, title, dname FROM mutable
JOIN schedule ON mutable.title like '%' || schedule.schdname || '%'
Or a sligtly more readable way:
SELECT id, title, dname FROM mutable
JOIN schedule ON POSITION(schedule.schdname in mutable.title)<>0
Are you actually using a wildcard with like? You don't say so above. If not you can replace like with IN. If you do want to do a wildcard join I'd recommend taking a substring of the columns and comparing that e.g.
names
james
jack
janice
select substr(names,1,2) as names_abbr
from names_table where names_abbr = (select ...)

SQL using where contains to return rows based on the content of another table

I need some help:
I have a table called Countries, which has a column named Town and a column named Country.
Then I have table named Stores, which has several columns (it is a very badly set up table) but the ones that are important are the columns named Address1 and Address2.
I want to return all of the rows in Stores where Address1 and Address2 contains the towns in the Countries table.
I have a feeling this is a simple solution but I just can't see it.
It would help if maybe you could use WHERE CONTAINS but in your parameters search in another table's column?
e.g.
SELECT *
FROM Stores
WHERE CONTAINS (Address1, 'Select Towns from Countries')
but obviously that is not possible, is there a simple solution for this?
You're close
SELECT * FROM Stores s
WHERE EXISTS (
SELECT * FROM Countries
WHERE CONTAINS(s.Address1, Town) OR CONTAINS(s.Address2, Town)
)
This would be my first attempt:
select * from stores s
where
exists
(
select 1 from countries c
where s.Address1 + s.Address2 like '%'+c.Town+'%'
)
Edit: Ooops just saw that you want the 'CONTAINS' clause. Then take Paul's solution