Scope of SQL Use statement & Insert Into Select - sql

USE DATABASE
insert into #Table -- Previously created temp table
(
Name
Number
Date
)
select 'Joe', 5, 'January 9th'
union all select 'Sam', 3, 'January 4th'
union all select 'Eleanor', 4, 'January 5th'
union all select 'Joseph', 1, 'January 6th'
My question is what is the scope of the USE statement when insert into select is not specifying a 'from' statement that clearly denotes what table in the database the information is coming from?
I've encountered an insert into select statement similar to this one and what I am struggling to understand is if the data is being created in the four select statements or if it is being searched for and found in the DATABASE. If it is being searched for how does Microsoft SQL Server Management studio know what table is being referred to?

Everything following USE database will be run in the context of the database chosen.
In this case, the USE accomplishes nothing, because your #temp table is stored in tempdb regardless of which database you're using, and your select is not accessing any tables, so it will return the hardcoded values regardless of database context as well.

If there is no FROM clause, then the data isn't coming from any table in any database. It is hard-coded into the INSERT query. If you're asking how does it know what table to insert the data into, that is specified in the INSERT INTO clause, and is in the context of the USE statement.
I'm suspicious of your question, because you insert into a temp table, which you comment as "previously created" and the scope of temp tables is an entirely different matter.

Related

How to create a temporary table without referring to permanent table i.e. without using select statement

Is there any way to create our own temporary table or using 'With' clause to create a table with our own columns and values without using any select statement from another permanent table in a query. That temporary table I want to refer in my main query.
Please help me with this.
Thanks.
You can certainly use a WITH however depending on the data you might have to use a lot of UNION ALL statements unless your requirement can allow to use some kind of recursive query. The below is for SQL-Server.
WITH temp_table(id, name) AS
(
SELECT 1, 'abc'
UNION ALL
SELECT 2, 'cde'
)
SELECT * FROM temp_table
You can read this for more details - https://learn.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-ver15

Does Oracle allow an SQL INSERT INTO using a SELECT statement for VALUES if the destination table has an GENERATE ALWAYS AS IDENTITY COLUMN

I am trying to insert rows into an Oracle 19c table that we recently added a GENERATED ALWAYS AS IDENTITY column (column name is "ID"). The column should auto-increment and not need to be specified explicitly in an INSERT statement. Typical INSERT statements work - i.e. INSERT INTO table_name (field1,field2) VALUES ('f1', 'f2'). (merely an example). The ID field increments when typical INSERT is executed. But the query below, that was working before the addition of the IDENTITY COLUMN, is now not working and returning the error: ORA-00947: not enough values.
The field counts are identical with the exception of not including the new ID IDENTITY field, which I am expecting to auto-increment. Is this statement not allowed with an IDENTITY column?
Is the INSERT INTO statement, using a SELECT from another table, not allowing this and producing the error?
INSERT INTO T.AUDIT
(SELECT r.IDENTIFIER, r.SERIAL, r.NODE, r.NODEALIAS, r.MANAGER, r.AGENT, r.ALERTGROUP,
r.ALERTKEY, r.SEVERITY, r.SUMMARY, r.LASTMODIFIED, r.FIRSTOCCURRENCE, r.LASTOCCURRENCE,
r.POLL, r.TYPE, r.TALLY, r.CLASS, r.LOCATION, r.OWNERUID, r.OWNERGID, r.ACKNOWLEDGED,
r.EVENTID, r.DELETEDAT, r.ORIGINALSEVERITY, r.CATEGORY, r.SITEID, r.SITENAME, r.DURATION,
r.ACTIVECLEARCHANGE, r.NETWORK, r.EXTENDEDATTR, r.SERVERNAME, r.SERVERSERIAL, r.PROBESUBSECONDID
FROM R.STATUS r
JOIN
(SELECT SERVERSERIAL, MAX(LASTOCCURRENCE) as maxlast
FROM T.AUDIT
GROUP BY SERVERSERIAL) gla
ON r.SERVERSERIAL = gla.SERVERSERIAL
WHERE (r.LASTOCCURRENCE > SYSDATE - (1/1440)*5 AND gla.maxlast < r.LASTOCCURRENCE)
) )
Thanks for any help.
Yes, it does; your example insert
INSERT INTO table_name (field1,field2) VALUES ('f1', 'f2')
would also work as
INSERT INTO table_name (field1,field2) SELECT 'f1', 'f2' FROM DUAL
db<>fiddle demo
Your problematic real insert statement is not specifying the target column list, so when it used to work it was relying on the columns in the table (and their data types) matching the results of the query. (This is similar to relying on select *, and potentially problematic for some of the same reasons.)
Your query selects 34 values, so your table had 34 columns. You have now added a 35th column to the table, your new ID column. You know that you don't want to insert directly into that column, but in general Oracle doesn't, at least at the point it's comparing the query with the table columns. The table has 35 columns, so as you haven't said otherwise as part of the statement, it is expecting 35 values in the select list.
There's no way for Oracle to know which of the 35 columns you're skipping. Arguably it could guess based on the identity column, but that would be more work and inconsistent, and it's not unreasonable for it to insist you do the work to make sure it's right. It's expecting 35 values, it sees 34, so it throws an error saying there are not enough values - which is true.
Your question sort of implies you think Oracle might be doing something special to prevent the insert ... select ... syntax if there is an identity column, but in facts it's the opposite - it isn't doing anything special, and it's reporting the column/value count mismatch as it usually would.
So, you have to list the columns you are populating - you can't automatically skip one. So you statement needs to be:
INSERT INTO T.AUDIT (IDENTIFIER, SERIAL, NODE, ..., PROBESUBSECONDID)
SELECT r.IDENTIFIER, r.SERIAL, r.NODE, ..., r.PROBESUBSECONDID
FROM ...
using the actual column names of course if they differ from the query column names.
If you can't change that insert statement then you could make the ID column invisible; but then you would have to specify it explicitly in queries, as select * won't see it - but then you shouldn't rely on * anyway.
db<>fiddle

How can I INSERT data into two tables simultaneously with only one sql script db2?

How would I insert into multiple tables with one sql script in db2
For example, insert a row into T1 DOCK_DOOR and then insert into T2 DOCK_DOOR_LANE multiple times based on the dock_door_sysid from the first table.
My first approach was the following. I was attempting to use a with with three inserts. on the other hand, doing to inserts on the second table is not and option if this can be automated with one insert.
thanks for any feedback
sql example
WITH ins AS (
INSERT INTO DBF1.DOCK_DOOR (DOCK_DOOR_SYSID,DOOR_NUMBER,DOOR_NAME,DOCK_SYSID,DOOR_SEQ,ENCRYPTION_CODE,RFID_ENBLD_FLAG,LANES_COUNT,CMNT_TEXT,CREATE_TS,CREATE_USERID,UPDATE_TS,UPDATE_USERID,VER_NUMBER,ACTIVE_FLAG,STATUS_SYSID,DOOR_TYPE_SYSID)
VALUES (nextval for DBF1.DOCK_DOOR_SEQ,'026','DOOR025',61,25,NULL,'N','2',NULL,current timestamp,'SQL_INSERT',current timestamp,'SQL_INSERT',0,NULL,1723,1142)
RETURNING door_number,dock_door_sysid),
ins2 AS (
INSERT INTO SIT.DOCK_DOOR_lane (DOCK_DOOR_LANE_SYSID,DOOR_LANE_ID,DOCK_DOOR_SYSID,LANE_ID,CREATE_TS,CREATE_USERID,UPDATE_TS,UPDATE_USERID,VER_NUMBER)
VALUES (nextval for DBF1.DOCK_DOOR_LANE_seq,door_number||''||'A',dock_door_sysid,'A',current timestamp},'SQL_INSERT',current timestamp,'SQL_INSERT',0)
SELECT door_number,dock_door_sysid FROM DBF1.DOCK_DOOR
RETURNING door_number,dock_door_sysid)
INSERT INTO DBF1.DOCK_DOOR_lane (DOCK_DOOR_LANE_SYSID,DOOR_LANE_ID,DOCK_DOOR_SYSID,LANE_ID,CREATE_TS,CREATE_USERID,UPDATE_TS,UPDATE_USERID,VER_NUMBER)
VALUES (nextval for DBF1.DOCK_DOOR_LANE_seq,door_number||''||'B',dock_door_sysid,'B',current timestamp},'SQL_INSERT',current timestamp,'SQL_INSERT',0)
SELECT door_number,dock_door_sysid FROM DBF1.DOCK_DOOR;
Table 1 = dock_door
Table 2 = Dock_door_lane
You could do it with a trigger on the dock_door table.
However, if you're on a recent, version on IBM i. You might be able to make use of data change table reference
Your statement would look something like this
insert into dock_door_lane
select <....>
from final table (insert into dock_door <...>)
I'm not sure it will work, as this article indicates that at least at a couple of years ago DB2 for i didn't support the secondary insert required.
This old SO question also seems to confirm that at least at v7.1, the double insert isn't supported.
If I get a chance, I'll run a test on a 7.2 system Monday.

Difference between INSERT INTO and INSERT ALL INTO

While I was inserting some records in table i found that..
INSERT INTO T_CANDYBAR_DATA
SELECT CONSUMER_ID,CANDYBAR_NAME,SURVEY_YEAR,GENDER,1 AS STAT_TYPE,OVERALL_RATING
FROM CANDYBAR_CONSUMPTION_DATA
UNION
SELECT CONSUMER_ID,CANDYBAR_NAME,SURVEY_YEAR,GENDER,2 AS STAT_TYPE,NUMBER_BARS_CONSUMED
FROM CANDYBAR_CONSUMPTION_DATA;
79 rows inserted.
INSERT ALL
INTO t_candybar_data VALUES (consumer_id,candybar_name,survey_year,gender,1,overall_rating)
INTO t_candybar_data VALUES (consumer_id,candybar_name,survey_year,gender,2,number_bars_consumed)
SELECT * FROM candybar_consumption_data
86 rows inserted.
I have read somewhere that INSERT ALL INTO automatically unions then why those difference is showing.
The problem is your queries are different—your first is with UNION and your second is without—so they are naturally inserting different numbers of values. As far as what INSERT ALL is versus a straight INSERT:
INSERT can be used for inserting new records to a single table.
INSERT ALL can be used for inserting new records to multiple tables based on the query condition.
So your assumption as stated here:
I have read somewhere that INSERT ALL INTO automatically unions then
why those difference is showing.
Is incorrect. INSERT ALL doesn’t have anything to do with UNION in any way. But that said, you might be mixing up UNION ALL as explained here.
The SQL UNION ALL operator is used to combine the result sets of 2 or
more SELECT statements. It returns all rows from the query (even if
the row exists in more than one of the SELECT statements).
Each SELECT statement within the UNION ALL must have the same number
of fields in the result sets with similar data types.

How might I insert an array of data into a database table?

I am developing an attendance management program, used to maintain the absence record of a student. Users of this software will need to enter various dates, updated once in a month: for instance, a list of dates on which a student was absent for that particular month would be entered, and my program must then store them into a database with each date added as a new row in the appropriate table.
I have the dates stored using arrays internally, how might I transfer these into the database? How should I proceed?
You have not mentioned the database system being used, so my reply is general in nature. The usual way to do this is to run multiple insert statements one after another:
INSERT INTO Table1 (FirstColumn, SecondColumn)
VALUES ('a', 'b');
INSERT INTO Table1 (FirstColumn, SecondColumn)
VALUES ('c', 'd');
INSERT INTO Table1 (FirstColumn, SecondColumn)
VALUES ('e', 'f');
GO
The trick way to do this is to use the UNION ALL statement:
INSERT INTO Table1 (FirstColumn, SecondColumn)
SELECT 'a', 'b'
UNION ALL
SELECT 'c', 'd'
UNION ALL
SELECT 'e', 'f'
GO
Versions of SQL Server prior to 2008 support only these methods. But SQL 2008 and MySQL 3.22 and above support the Row construction method as well:
INSERT INTO Table1 (FirstColumn, SecondColumn)
VALUES ('a', 'b'),
VALUES ('c', 'd'),
VALUES ('e', 'f')
GO
Now you can use any of the above methods to iterate through your array and add individual attendance rows to the database.
foreach($arrayName as $arrayValue) {
// run your query here!
}
for example:
$myArray = array('apple','orange','grape');
foreach($myArray as $arrayFruit) {
$query = "INSERT INTO `Fruits` (`FruitName`) VALUES ('" . $arrayFruit . "')";
mysql_query($query, $connection);
}
does that makes sense / fit what you were thinking?
Do you want to store the dates seperately so you can juggle with them, query them, etc.?
Or do you just want to store the array as is?
If you want to store the dates separately you may want to create a table with an FK to students, a column for date and a column for the nature of the date, like absence, late, ...
Then you would indeed store the single dates into that table. If you must, by iterating but if you can with one of Cerbrus' solutions!. It is not recommended to have db-queries within loops.
If you just need to store that array somewhere, you can serialize it and store the serialized string in a text or varchar column.
What language and what type of database are you using? Is this a web application? A desktop application? We can't help you without more information.
Depending on your situation, any of the above solutions could work. Or you could even load all of the attendance records at once as a CSV or XML document. Perhaps a little more research on your part will help you ask a more useful question?
Iterate over the array and execute insert SQL for each date.