Creation of temp table to minus against actual table - sql

I am testing an ETL load at the moment and want to create a temporary table that combines a number of rules so that I can do a minus against this temp table and the actual loaded table.
I've tried various things but keep getting the same message stating "FROM keyword is not found where expected"
My mentor is off on holiday and would appreciate if someone can offer me some assistance.
Create table tbl_HT_CUST_PHNUM_TEMP as
Select a.CONT_ID as CONT_ID,
a.TELEPHONE_NO as TELEPHONE_NO,
ROW_ID IS NULL,
STATUS_ID IS NULL,
SystemTableID IS NULL,
INITIAL_POPULATION_TS as INITIAL_POPULATION_TS,
BUSINESS_DATE_EXT as BUSINESS_DATE_EXT,
UPDATE_DATE_TIME as UPDATE_DATE_TIME,
DATE_ENDED as DATE_ENDED
CUSTOMERMAPPINGKEY IS NULL
from <schema>.tbl_HT_CUST_PHNUM a;

You have your ass confused with iss. Assuming your database supports create table as, then I suspect you want something like this:
Create table tbl_HT_CUST_PHNUM_TEMP as
Select a.CONT_ID as CONT_ID,
a.TELEPHONE_NO,
NULL as ROW_ID,
NULL as STATUS_ID,
NULL as SystemTableID,
a.INITIAL_POPULATION_TS,
a.BUSINESS_DATE_EXT,
a.UPDATE_DATE_TIME,
a.DATE_ENDED,
NULL as CUSTOMERMAPPINGKEY
from <schema>.tbl_HT_CUST_PHNUM a;
Note that you don't need as to specify a column name that is coming directly from a table.

Related

Append query error

My primary key of Specialization table is complex and consists of two columns: Specialization_id and Specialty_id(which is foreign key of Specialty table).
I am going to make insert query by creating a new SPECIALIZATION of an existing specialty.
I have some specializations in my table already, primary key for one specialty with id = 1 looks like (1,1) (2,1), with id = 2 looks like (1,2) (2,2).
Now I am going to add a new Specialization to Specialization table, but this Specialization should reference to existing Specialty.
My idea is
INSERT INTO Specialization ( Specialization_name, Specialization_id, Specialty_id )
VALUES( 'Network technologies','(SELECT Max(Specialization_id) FROM Specialization WHERE Specialty_id = '2')+1', '2');
I've tried with '' clauses and without it, still, I am getting errors.
What should I do here?
In a database like MySQL or ORACLE you should not programatically increment the primary key. Instead you should set the field to AUTOINCREMENT when you design the database.
That would change your INSERT statement to:
INSERT INTO Specialization (Specialization_name, Specialty_id)
VALUES('Network technologies', '2')
which is not only much easier, it is safer.
edited to add: Are you sure Specialty_id is a string? I would think it would be some kind of number.
Your main error is the quotes, since your subquery is quoted it will get processed as a string and not a query.
Also, you don't need to use a subquery if you don't have a main query:
INSERT INTO Specialization ( Specialization_name, Specialization_id, Specialty_id )
SELECT 'Network technologies' As a, Max(Specialization_id)+1 As b, 2 As c
FROM Specialization WHERE Specialty_id = 2
However, like dstudeba said, relying on autonumbers for creating new IDs is probably smarter.

Is it possible to CREATE TABLE with a column that is a combination of other columns in the same table?

I know that the question is very long and I understand if someone doesn't have the time to read it all, but I really wish there is a way to do this.
I am writing a program that will read the database schema from the database catalog tables and automatically build a basic application with the information extracted from the system catalogs.
Many tables in the database can be just a list of items of the form
CREATE TABLE tablename (id INTEGER PRIMARY KEY, description VARCHAR NOT NULL);
so when a table has a column that references the id of tablename I just resolve the descriptions by querying it from the tablename table, and I display a list in a combo box with the available options.
There are some tables however that cannot directly have a description column, because their description would be a combination of other columns, lets take as an example the most important of those tables in my first application
CREATE TABLE bankaccount (
bankid INTEGER NOT NULL REFERENCES bank,
officeid INTEGER NOT NULL REFERENCES bankoffice,
crc INTEGER NOT NULL,
number BIGINT NOT NULL
);
this as many would know, would be the full account number for a bank account, in my country it's composed as follows
[XXXX][XXXX][XX][XXXXXXXXXX]
^ ^ ^ ^
bank id | crc account number
|
|_ bank office id
so that's the reason of the way my bankaccount table is structured as is.
Now, I would like to have the complete bank account number in a description column so I can display it in the application without giving a special treatment to this situation, since there are some other tables with similar situation, something like
CREATE TABLE bankaccount (
bankid INTEGER NOT NULL REFERENCES bank,
officeid INTEGER NOT NULL REFERENCES bankoffice,
crc INTEGER NOT NULL,
number BIGINT NOT NULL,
description VARCHAR DEFAULT bankid || '-' || officeid || '-' || crc || '-' || number
);
Which of course doesn't work since the following error is raised1
ERROR: cannot use column references in default expression
If there is any different approach that someone can suggest, please feel free to suggest it as an answer.
1 This is the error message given by PostgreSQL.
What you want is to create a view on your table. I'm more familiar with MySQL and SQLite, so excuse the differences. But basically, if you have table 'AccountInfo' you can have a view 'AccountInfoView' which is sort of like a 'stored query' but can be used like a table. You would create it with something like
CREATE VIEW AccountInfoView AS
SELECT *, CONCATENATE(bankid,officeid,crc,number) AS FullAccountNumber
FROM AccountInfo
Another approach is to have an actual FullAccountNumber column in your original table, and create a trigger that sets it any time an insert or update is performed on your table. This is usually less efficient though, as it duplicates storage and takes the performance hit when data are written instead of retrieved. Sometimes that approach can make sense, though.
What actually works, and I believe it's a very elegant solution is to use a function like this one
CREATE FUNCTION description(bankaccount) RETURNS VARCHAR AS $$
SELECT
CONCAT(bankid, '-', officeid, '-', crc, '-', number)
FROM
bankaccount this
WHERE
$1.bankid = this.bankid AND
$1.officeid = this.officeid AND
$1.crc = this.crc AND
$1.number = this.number
$$ LANGUAGE SQL STABLE;
which would then be used like this
SELECT bankaccount.description FROM bankaccount;
and hence, my goal is achieved.
Note: this solution works with PostgreSQL only AFAIK.

use nested table value in where clause(oracle)

i am fairly new to the Oracle DBMS and would like to know how to use a member of a nested table in a where clause
specifically
i have a nested table named poll_nest
SQL> desc poll_nest
Name Null? Type
----------------------------------------- -------- ----------------------------
ID VARCHAR2(20)
CID VARCHAR2(20)
which was created as follows
create or replace type voter_arrive as object(id varchar(20),cid varchar(20));
create or replace type poller as table of voter_arrive;
and then it was inserted into the election table as poll_nest
SQL> desc election;
Name Null? Type
----------------------------------------- -------- ----------------------------
REGION VARCHAR2(20)
STIME TIMESTAMP(6)
ETIME TIMESTAMP(6)
VOTES POLLER
i need to take some actions based on the value of the cid attribute of poll_nest that is currently entered(like incrementing a value based on the cid)
so i used an after trigger in which i did this:
select distinct t.cid into voted from election e,table(e.votes) t where t.cid=:new.votes.cid;
but i get a compilation error.
i saw this answer and this too:
Oracle Nested Table predicate in where clause
but couldn't understand how they work..
could someone please help me with the syntax?
poll_nest is not a nested table. Its table that stores PL SQL object.
From http://www.orafaq.com/wiki/NESTED_TABLE :
NESTED TABLE is an Oracle data type used to support columns containing multivalued attributes, in this case, columns that can hold an entire sub-table.
You can insert value in table of object type by first instantiating object constructor like
insert into poll_nest values (voter_arrive('122','112'));
For accessing the inserted value you can use
select e.voter.arrive.cid from poll_tab e where e.voter_arrive.id = '122';
check out this link too: http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/objects.htm
Update:
I looked up oracle documentation http://docs.oracle.com/cd/A97630_01/appdev.920/a96624/05_colls.htm , and I found that poller is a nested table. I don't know why they call it nested table, it should be called PL/SQL table only.
I assumed poll_nest to be like, and answered the question
CREATE TABLE APPS.POLL_NEST
(
VOTER APPS.VOTER_ARRIVE
)
but now I think you have created table and objects like
create or replace type voter_arrive as object(id varchar(20),cid varchar(20));
create or replace type poller as table of voter_arrive;
create table election(
REGION VARCHAR2(20),
STIME TIMESTAMP(6),
ETIME TIMESTAMP(6),
VOTES POLLER
) NESTED TABLE VOTES STORE AS VOTES_TAB;
For each region(which should be unique), you are going to save records in VOTES nested table .if I am correct
INSERT INTO election
VALUES ( 'A',
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP,poller(voter_arrive('100','001'),voter_arrive('200','002')) )
poller() is a constructor of nested table type poller. All values passed to constructor will create new row in poller. So, you can perform insert and update in election table like
INSERT INTO table (select e.votes from election e where region ='A') values((voter_arrive('300','003')))
To access individual row in poller nested table you need to use TABLE() function like this:
select * from table (select e.votes from election e where region ='A') a where a.id = 100

How do I properly SELECT INTO #TempTable Multiple times to return a single resultset?

I'm trying to write a stored procedure for Crystal Reports by combining multiple queries into a single resultset (Crystal doesn't support multiple results in one report).
The result set I'm trying to get combines columns from both tables.
In the SP, I declare #temptable and the columns (because the two tables i'm querying have different columns).
DECLARE #TEMPNEWBILLING TABLE
(
ACCOUNT DECIMAL null,
CLIENT NVARCHAR null,
TIMESTAMP INT null,
BILLING DECIMAL null,
CALLKIND INT null,
HITK1 DECIMAL null,
HITK2 DECIMAL null,
HIDISC DECIMAL null,
HITALK DECIMAL null,
HIPTCH DECIMAL null,
HICONF DECIMAL null,
HIHOLD DECIMAL null,
PTCH DECIMAL null,
SUPERTIME DECIMAL null
)
I then SELECT from both tables INTO the temp table:
SELECT Account, Client, Timestamp, Billing, CallKind, HiTk1, HiTk2, HiDisc, HiTalk, HiPtch, HiConf, HiHold, Ptch
INTO TEMPNEWBILLING
FROM
mCallEnd
WHERE billing = cast(#BILLINGNUMBER as decimal)
AND Timestamp > #STARTITIME
AND Timestamp < #ENDITIME
AND CallKind in (0,1,2,3,4,16)
SELECT
Billing, SuperTime
INTO TEMPNEWBILLING
FROM
mClientMaint
WHERE billing = cast(#BILLINGNUMBER as decimal)
AND Timestamp > #STARTITIME
AND Timestamp < #ENDITIME
And finally, I just get all data from the temp table.
SELECT * FROM #TEMPNEWBILLING
Unfortunately, something is going wrong, as when I run the SP, I get an error that
There is already an object named 'TEMPNEWBILLING' in the database.
I've checked it out and it seems that the first query is running, but the error gets thrown at the second Select Into. I must be doing this wrong, as I get the same error if I use # tables or # tables (i.e. delcare the table vs. create the table).
Is the prospect of filling a temp table with the results of two queries simply not possible? Am I using the wrong tool for the job?
SELECT... INTO creates a new table.
You'll want to reverse it:
INSERT INTO #TEMPNEWBILLING
(Columns...)
SELECT (your select query here)
You'll want to declare the table (technically it's a table variable since you're using the # sign) as you did. Then use INSERT INTO... SELECT... for all of your inserts.
In your code, you are not using the variable table youe defined, instead you are trying to put the results into the same physical table. Try this instead:
INSERT INTO #TEMPNEWBILLING(Account, Client, Timestamp, Billing, CallKind, HiTk1, HiTk2, HiDisc, HiTalk, HiPtch, HiConf, HiHold, Ptch)
SELECT Account, Client, Timestamp, Billing, CallKind, HiTk1, HiTk2, HiDisc, HiTalk, HiPtch, HiConf, HiHold, Ptch
FROM
mCallEnd
WHERE billing = cast(#BILLINGNUMBER as decimal)
AND Timestamp > #STARTITIME
AND Timestamp < #ENDITIME
AND CallKind in (0,1,2,3,4,16)
INSERT INTO #TEMPNEWBILLING(Billing, SuperTime)
SELECT
Billing, SuperTime
FROM
mClientMaint
WHERE billing = cast(#BILLINGNUMBER as decimal)
AND Timestamp > #STARTITIME
AND Timestamp < #ENDITIME
You need to use INSERT once the table is already created. Also, you're using a table variable, so you need to include the # at the beginning of the name when referring to it. Since you're declaring the table variable at the start, both statements should actually be INSERT and not SELECT INTO.
SELECT INTO tries to create a new table. In your code you basically declare a table variable (which never gets used), then your first SELECT INTO creates a permanent table with the name TEMPNEWBILLING, then your second SELECT INTO tries to create a table with the same exact name - hence the error.

Can I create a table with check constrain whose values are dependent on sql query

Is it possible to create a table which has a check constraint on one of the column whose value lies within the result set given by another sql query
eg.
create table tablename
(
name varchar(10),
rollno int
)check rollno in (select rollno from anotherDatabase.TableName,candidateRoll)
or any thing like that.
I dont have to use it anywhere but still want to know.
If you can't achieve what you want with a foreign key reference, so you can if you wrap the SELECT statement in a function call.
Your check constraint expression may look something like:
(dbo.SomeFunction([col1]) != 0)
The function might look like this (assuming the column is a varchar):
create function dbo.SomeFunction(#arg varchar(max))
returns bit
as
begin
return
(
select count(*) from SomeOthertable where col2 = #arg
)
end
EDIT (2010/06/9): Regarding Anthony's comment, my testing has shown that a count(*) value of greater than 1 is still returned as 1. So it would seem that the function is okay, even though it should probably explicitly return 1 or 0. Or, if you are interested in the actual rowcount, change the return type from BIT to INT.
Yes: foreign key for same database links
create table tablename
(
name varchar(10),
rollno int FOREIGN KEY (candidateRoll) REFERENCES OtherTableName (candidateRoll)
)
If it's a different database then use code e.g. insert via stored proc or enforce via a trigger