SQL: Column count does not match - sql

I'm trying to insert values from two tables into a new table, but I keep getting the 'column count does not match' when it does. This is what I have so far:
create table contribution (
contb_id integer primary key auto_increment,
cand_id varchar(12),
contbr_id varchar(12),
amount numeric(8,2),
date varchar(20),
election_type varchar(20),
tran_id varchar(20),
foreign key (cand_id) references candidate,
foreign key (contbr_id) references contributor
);
and to insert the values into it:
INSERT INTO contribution (cand_id, contbr_id, amount, date, election_type, tran_id)
SELECT (cand_id, cb.contbr_id, contb_receipt_amt, contb_receipt_dt, election_tp, tran_id)
FROM campaign, contributor cb
Any help would be greatly appreciated!

Essentially the answer is here: https://stackoverflow.com/a/5391390/12672179
For your case when you are inserting using select you should NOT have the brackets. Brackets in a select statement act very funky and essentially is making each column combine into 1 in its view. So to fix the column count issue in your INSERT statement just do this
INSERT INTO contribution (cand_id, contbr_id, amount, date, election_type, tran_id)
SELECT cand_id, cb.contbr_id, contb_receipt_amt, contb_receipt_dt, election_tp, tran_id
FROM campaign, contributor cb
Additionally this is still wrong as you cannot do two from tables in the same FROM instead you should JOIN the second table ON a value where the two tables match (In other words the foreign key field). I'm not going to tell you which type of JOIN to use as that depends on your data and if every single value has a link or not.
Finally you should also include a WHERE so sql knows which values to fetch if you only want to do specific and not all.

Related

I have come across an error in SQL and cannot fix this foreign key error. See desc for more information

I have been receiving the error code 1452, i am trying to add keys to a table to keep data unqiue and useable in other tables. i have created the tables and can use the information already entered but i want to make the databases properly so i am trying to use the keys. please refer to the code below.
CREATE TABLE CUSTOMERS (
CustID varchar(50) NOT NULL,
Client_Name varchar(50) NOT NULL,
Client_Address varchar(80) NOT NULL,
PRIMARY KEY (CustID)
);
CREATE TABLE ORDERS (
Order_ID VARCHAR(10) NOT NULL,
Client_NameID varchar(50) NOT NULL,
Dates varchar(10) NOT NULL,
PRIMARY KEY (Order_ID),
FOREIGN KEY (Client_NameID) REFERENCES CUSTOMERS(CustID)
);
SELECT * FROM CUSTOMERS;
SELECT * FROM ORDERS;
DESCRIBE Orders; /*Used to display the Table*/
ALTER TABLE ORDERS ADD Dates VARCHAR(10); /*Used to add columns into the table*/
ALTER TABLE ORDERS DROP COLUMN Date; /*Used to remove column from the table*/
INSERT INTO CUSTOMERS (CustID, Client_Name, Client_Address) VALUES
('168', 'Coventry Building Services', 'Units 2-4, Binley Industrial Estate, CV3 2WL'), /*Used to insert values into the columns*/
('527', 'Allied Construction LTD', '34, Lythalls La Industrial Estate, NG18 5AH'),
('169', 'Ricoh Builds Ltd', 'Unit 12, Stoneleigh Park, CV8 2UV'),
('32', 'British Embassy in Tehran', '198 Ferdowski Avenue Tehran 11316-91144 Iran');
INSERT INTO ORDERS (Order_ID, Client_NameID, Dates) VALUES
('CON-2237', 'Coventry Building Services', '2014-12-14'),
('CON-3664', 'Allied Construction LTD', '2015-01-16'),
('CON-2356', 'Ricoh Builds Ltd', '2015-02-12'),
('CON-1234', 'British Embassy in Tehran', '2015-04-16');
DELETE FROM ORDERS WHERE Client_Name='Coventry Building Services'; /*Used to delete specific
data from the specific row and column wherever applicable*/
DROP TABLE CUSTOMERS;
DROP TABLE ORDERS;
Below are the tables im trying to work with, all of them will pretty much have a key that links them together if necessary
The CustomerS Table which only includes a Primary Key
The Orders Table which includes a Primary and Foreign key
The problem is with the inserts into table orders. Your foreign key on Client_NameIDreferencesCUSTOMERS(CustID), but you are giving the CUSTOMERS(Client_Name) instead.
You probably want:
INSERT INTO ORDERS (Order_ID, Client_NameID, Dates) VALUES
('CON-2237', 'CON-2237', '2014-12-14');
('CON-3664', 'CON-3664', '2015-01-16');
('CON-2356', 'CON-2356', '2015-02-12');
('CON-1234', 'CON-1234', '2015-04-16');
Notes:
You can perform all inserts in a single query by passing several tuples of values, as shown above
Don't store dates as strings; instead, use the date datatype, which exists for that purpose. I changed the query so it uses proper date literals, which would fit in a date column
it is unclear why you want to use the same value for the primary key of customers and orders - to me, this makes things harder to follow. I would recommend just using auto-incremented primary keys

How to select from table A and then insert selected id inside table B with one query?

I'm trying to implement a very basic banking system.
the goal is to have different types of transactions ( deposit, withdraw, transfer ) inside a table and refer to them as IDs inside transaction tables.
CREATE TABLE transaction_types (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
name VARCHAR UNIQUE NOT NULL
)
CREATE TABLE transactions (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
type_id INTEGER NOT NULL,
amount FLOAT NOT NULL
)
What I'm trying to accomplish is:
When inserting into transactions table no record can have an invalid type_id ( type_id should exist in transaction_types table )
First of all get type_id from transaction_types table and then insert inside transactions table, with one query ( if it's possible, I'm fairly new )
I'm using Node.js/Typescript and PostgreSQL, any help is appreciated a lot.
For (1): modify Transactions table definition by adding REFERENCES transaction_types(id) to the end of the type_id column definition prior to the comma.
For (2), assuming you know the name of the transaction_type, you can accomplish this by:
INSERT INTO transactions(type_id, amount)
VALUES ((SELECT id from transaction_types WHERE name = 'Withdrawal'), 999.99)
By the way, my PostgreSQL requires SERIAL instead of INTEGER AUTOINCREMENT

SQL Server trigger can't insert

I beginning to learn how to write trigger with this basic database.
I'm also making my very 1st database.
Schema
Team:
TeamID int PK (TeamID int IDENTITY(0,1) CONSTRAINT TeamID_PK PRIMARY KEY)
TeamName nvarchar(100)
History:
HistoryID int PK (HistoryID int IDENTITY(0,1) CONSTRAINT HistoryID_PK PRIMARY KEY)
TeamID int FK REF Team(TeamID)
WinCount int
LoseCount int
My trigger: when a new team is inserted, it should insert a new history row with that team id
CREATE TRIGGER after_insert_Player
ON Team
FOR INSERT
AS
BEGIN
INSERT INTO History (TeamID, WinCount, LoseCount)
SELECT DISTINCT i.TeamID
FROM Inserted i
LEFT JOIN History h ON h.TeamID = i.TeamID
AND h.WinCount = 0 AND h.LoseCount = 0
END
Executed it returns
The select list for the INSERT statement contains fewer items than the insert list. The number of SELECT values must match the number of INSERT columns.
Please help thank. I'm using SQL Server
The error text is the best guide, it is so clear ..
You try inserting one value from i.TeamID into three columns (TeamID,WinCount,LoseCount)
consider these WinCount and LoseCount while inserting.
Note: I Think the structure of History table need to revisit, you should select WinCount and LoseCount as Expressions not as actual columns.
When you specify insert columns, you say which columns you will be filling. But in your case, right after insert you select only one column (team id).
You either have to modify the insert to contain only one column, or select, to retrieve 3 fields as in insert.
If you mention the columns where values have to be inserted(Using INSERT-SELECT).
The SELECT Statement has to contain the same number of columns that have been specified to be inserted. Also, ensure they are of the same data type.(You might face some issues otherwise)

Database Normalization using Foreign Key

I have a sample table like below where Course Completion Status of a Student is being stored:
Create Table StudentCourseCompletionStatus
(
CourseCompletionID int primary key identity(1,1),
StudentID int not null,
AlgorithmCourseStatus nvarchar(30),
DatabaseCourseStatus nvarchar(30),
NetworkingCourseStatus nvarchar(30),
MathematicsCourseStatus nvarchar(30),
ProgrammingCourseStatus nvarchar(30)
)
Insert into StudentCourseCompletionStatus Values (1, 'In Progress', 'In Progress', 'Not Started', 'Completed', 'Completed')
Insert into StudentCourseCompletionStatus Values (2, 'Not Started', 'In Progress', 'Not Started', 'Not Applicable', 'Completed')
Now as part of normalizing the schema I have created two other tables - CourseStatusType and Status for storing the Course Status names and Status.
Create Table CourseStatusType
(
CourseStatusTypeID int primary key identity(1,1),
CourseStatusType nvarchar(100) not null
)
Insert into CourseStatusType Values ('AlgorithmCourseStatus')
Insert into CourseStatusType Values ('DatabaseCourseStatus')
Insert into CourseStatusType Values ('NetworkingCourseStatus')
Insert into CourseStatusType Values ('MathematicsCourseStatus')
Insert into CourseStatusType Values ('ProgrammingCourseStatus')
Insert into CourseStatusType Values ('OperatingSystemsCourseStatus')
Insert into CourseStatusType Values ('CompilerCourseStatus')
Create Table Status
(
StatusID int primary key identity(1,1),
StatusName nvarchar (100) not null
)
Insert into Status Values ('Completed')
Insert into Status Values ('Not Started')
Insert into Status Values ('In Progress')
Insert into Status Values ('Not Applicable')
The modified table is as below:
Create Table StudentCourseCompletionStatus1
(
CourseCompletionID int primary key identity(1,1),
StudentID int not null,
CourseStatusTypeID int not null CONSTRAINT [FK_StudentCourseCompletionStatus1_CourseStatusType] FOREIGN KEY (CourseStatusTypeID) REFERENCES dbo.CourseStatusType (CourseStatusTypeID),
StatusID int not null CONSTRAINT [FK_StudentCourseCompletionStatus1_Status] FOREIGN KEY (StatusID) REFERENCES Status (StatusID),
)
I have few question on this:
Is this the correct way to normalize it ? The old table was very helpful to get data easily - I can store a student's course status in a single row, but now 5 rows are required. Is there a better way to do it?
Moving the data from the old table to this new table seems to be not an easy task. Can I achieve this using a query or I have to manually to do this ?
Any help is appreciated.
vou could also consider storing results in flat table like this:
studentID,courseID,status
1,1,"completed"
1,2,"not started"
2,1,"not started"
2,3,"in progress"
you will also need additional Courses table like this
courserId,courseName
1, math
2, programming
3, networking
and a students table
students
1 "john smith"
2 "perry clam"
3 "john deere"
etc..you could also optionally create a status table to store the distinct statusstrings statusstings and refer to their PK instead ofthestrings
studentID,courseID,status
1,1,1
1,2,2
2,1,2
2,3,3
... etc
and status table
id,status
1,"completed"
2,"not started"
3,"in progress"
the beauty of this representation is: it is quite easy to filter and aggregate data , i.e it is easy to query which subjects a particular person have completed, how many subjects are completed by an average student, etc. this things are much more difficult in the columnar design like you had. you can also easily add new subjects without the need to adapt your tables or even queries they,will just work.
you can also always usin SQLs PIVOT query to get it to a familiar columnar presentation like
name,mathstatus,programmingstatus,networkingstatus,etc..
but now 5 rows are required
No, it's still just one row. That row simply contains identifiers for values stored in other tables.
There are pros and cons to this. One of the main reasons to normalize in this way is to protect the integrity of the data. If a column is just a string then anything can be stored there. But if there's a foreign key relationship to a table containing a finite set of values then only one of those options can be stored there. Additionally, if you ever want to change the text of an option or add/remove options, you do it in a centralized place.
Moving the data from the old table to this new table seems to be not an easy task.
No problem at all. Create your new numeric columns on the data table and populate them with the identifiers of the lookup table records associated with each data table record. If they're nullable, you can make them foreign keys right away. If they're not nullable then you need to populate them before you can make them foreign keys. Once you've verified that the data is correct, remove the old de-normalized columns. Done.
In StudentCourseCompletionStatus1 you still need 2 associations to Status and CourseStatusType. So I think you should consider following variant of normalization:
It means, that your StudentCourseCompletionStatus would hold only one CourseStatusID and another table CourseStatus would hold the associations to CourseType and Status.
To move your data you can surely use a query.

SQL database query display extra dates

I am making a database with postgresql 9.1
Given tables:
CREATE TABLE rooms(
room_number int,
property_id int,
type character varying,
PRIMARY KEY (room_number, property_id)
);
Insert into rooms values (1,1,double),(2,1,double),(3,1,triple)
CREATE TABLE reservations(
reservation_ID int,
property_id int,
arrival date,
departure date,
room_num int,
PRIMARY KEY(reservation_ID,property_id)
FOREIGN KEY (room_number, property_id)
);
INSERT INTO orders VALUES (1,1,2013-9-27,2013-9-30,1),
(2,1,2013-9-27,2013-9-28,2),
(3,1,2013-9-29,2013-9-30,3);
I want to give 2 dates and check availability in between. So at the 1st column should apear:
all the dates between the given and
additional one column for every type of the room displaying the availability.
So my result, given 2013-9-27 & 2013-9-30 as input, must be sth like this:
I think the best solution would be use both generate_series() and crosstab() to create a dynamic table. Moreover you can use a left join from a CTE to your data tables so you get better information. Something like:
WITH daterange as (
SELECT s::date as day FROM generate_series(?, ?, '1 day')
)
SELECT dr.day, sum(case when r.type = 'double' then r.qty else 0) as room_double,
sum(case when r.type = 'triple' then r.qty else 0) as room_triple....
);
But note that crosstab would make the second query a little easier.