column violate foreign key constraints - javascript

I'm trying to create a relationship between two tables, however i seem to get, some issues when i try to insert my object to postgres database. i keep getting following error: insert or update on table "tournament" violates foreign key constraint "tournament_league_id_foreign". which i guess is related to my knex syntax?
Insert into db
var data = {
id: id,
name: name,
league_id: leagueId
};
var query = knex('tournament').insert(data).toString();
query += ' on conflict (id) do update set ' + knex.raw('name = ?, updated_at = now()',[name]);
knex.raw(query).catch(function(error) {
log.error(error);
})
Knex tables
knex.schema.createTable('league', function(table) {
table.increments('id').primary();
table.string('slug').unique();
table.string('name');
table.timestamp('created_at').notNullable().defaultTo(knex.raw('now()'));
table.timestamp('updated_at').notNullable().defaultTo(knex.raw('now()'));
}),
knex.schema.createTable('tournament', function(table) {
table.string('id').primary();
table.integer('league_id').unsigned().references('id').inTable('league');
table.string('name');
table.boolean('resolved');
table.timestamp('created_at').notNullable().defaultTo(knex.raw('now()'));
table.timestamp('updated_at').notNullable().defaultTo(knex.raw('now()'));
})

When you created the tournament table, for the column league_id you you specified that .references('id').inTable('league'). This means that for every row in that table, there must exist a row in the table league whose id is the same as the value of the league_id field in the former row. Apparently in your insert (is this your only insert?) you are adding a row to tournament whose league_id does not exist in league. As a rule, the foreign constraint (i.e. the .references part) implies that you must create the league first and then tournaments in that league (which actually makes sense).

Related

INSERT INTO table VALUES float string from postman input

I'm trying to create a new course row into my Courses database in postman and I cannot get the syntax correct.
I've got 159 values that need to be added into a single course. Any chance I can summarise them instead of having to write down all the values?
Currently this is my query:
const addCourse = "INSERT INTO courses VALUES (value1 'value2','value3', 'value4', 'value5', 'value6', 'value7', 'value8', 'value9', 'value10', 'value11', 'value12', 'value13', 'value14', 'value15', 'value16', 'value17', 'value18', 'value19', 'value20', 'value21', 'value22', 'value23', 'value24', 'value25', 'value26', 'value27', 'value28', 'value29', 'value30', 'value31', 'value32', 'value33', 'value34', 'value35', 'value36', 'value37', 'value38', 'value39', 'value40', 'value41', 'value42', 'value43', 'value44', 'value45', 'value46', 'value47', 'value48', 'value49', 'value50', 'value51', 'value52', 'value53', 'value54', 'value55', 'value56', 'value57', 'value58', 'value59', 'value60', 'value61', 'value62', 'value63', 'value64', 'value65', 'value66', 'value67', 'value68', 'value69', 'value70', 'value71', 'value72', 'value73', 'value74', 'value75', 'value76', 'value77', 'value78', 'value79', 'value80', 'value81', 'value82', 'value83', 'value84', 'value85', 'value86', 'value87', 'value88', 'value89', 'value90', 'value91', 'value92', 'value93', 'value94', 'value95', 'value96', 'value97', 'value98', 'value99', 'value100', 'value101', 'value102', 'value103', 'value104', 'value105', 'value106', 'value107', 'value108', 'value109', 'value110', 'value111', 'value112', 'value113', 'value114', 'value115', 'value116', 'value117', 'value118', 'value119', 'value120', 'value121', 'value122', 'value123', 'value124', 'value125', 'value126', 'value127', 'value128', 'value129', 'value130', 'value131', 'value132', 'value133', 'value134', 'value135', 'value136', 'value137', 'value138', 'value139', 'value140', 'value141', 'value142', 'value143', 'value144', 'value145', 'value146', 'value147', 'value148', 'value149', 'value150', 'value151', 'value152', 'value153', 'value154', 'value155', 'value156', 'value157 ', 'value158' )"
This is my courseController code:
const addCourse = (req, res) => {
console.log(req.body);
const { id_curso } = req.body;
//check Curso exists
pool.query(queries.checkIdCursoExists, [id_curso], (error, results) => {
if (results.rows.length) {
res.send("Este curso ja existe.");
}
// add course
pool.query(queries.addCourse),
(error, results) => {
if (error) throw error;
res.status(201).send("Curso criado com sucesso");
};
});
};
The problem I encounter is this error message whether I have value1 in quotes or not:
error: type "value1" does not exist'
The course is not posted onto my database.
The path to your answer lies in your INSERT statement. I guess your courses table has 159 columns in it. (That is a great many columns and may suggest the need to normalize your table. SQL handles multiple-row data more efficiently than multiple-column data where it makes sense to do so. But you did not ask about that.)
The INSERT syntax is either this:
INSERT INTO tbl (col1, col2, col3) VALUES (const, const, const);
or this:
INSERT INTO tbl VALUES (const, const, const);
The first syntax allows you to insert a row without giving values for every column in the table. You use the second syntax. It requires you to give one constant value for each column of your table. But your insert looks like this:
INSERT INTO courses VALUES (value1 'value2', ... , 'value158' )"
I see some problems with this.
You only have 158 values, but your question says you have 159.
value1, the first value in your list, isn't a constant.
You need a comma after your first value.
All your value constants are text strings. Yet you mentioned float in the title of your question.

How to apply conditional put on DynamoDB?

I have a dynamoDB table called Cheque to represent a tables' cheque in a restaurant / bar.
I want to apply a conditional put request on this table so that a new table can only be created if the following conditions are meet:
tableNumber does not currently exist AND
restaurnatId does not currently exist AND
isOpen status on the table is false (i.e. cheque is not open)
I am creating my DynamoDB in Terraform like so:
resource "aws_dynamodb_table" "ChequesDDB" {
name = "Cheques_${var.env_name}"
hash_key = "id"
billing_mode = "PROVISIONED"
read_capacity = 5
write_capacity = 5
stream_enabled = true
stream_view_type = "NEW_AND_OLD_IMAGES"
attribute {
name = "id"
type = "S"
}
attribute {
name = "tableNumber"
type = "N"
}
global_secondary_index {
name = "TableNumber"
hash_key = "tableNumber"
write_capacity = 5
read_capacity = 5
projection_type = "ALL"
}
}
Note: I am unsure if I need to set my tableNumber as a secondary index but plese let me know if this is not required.
I am then trying to create a new cheque in the DynamoDB table with the following code:
const tableData: Cheque = {
id: randomUUID(),
isOpen: true,
tableNumber: cheque.tableNumber,
restaurantId: cheque.restaurantId,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
const params: DynamoDB.DocumentClient.PutItemInput = {
TableName: env.CHEQUE_DDB,
Item: tableData,
ConditionExpression: "attribute_not_exists(tableNumber)"
};
await this.db.put(params).promise();
To start with, I am only trying to apply one condition which is to ensure the tableNumber doesn't already exist.
But everytime I run this code, it creates a new entry in the table and I end up with multiple cheques open with table number x.
If I update my conditional expression to be attribute_not_exists(id) then it appears to stop other entries from being opened with the same id. Is this because the id is the primary key?
How can I apply these conditions to fields that are not primary keys and prevent multiple cheques being opened with the same table number?
A conditional check is only placed on a single item, in your case you generate a unique each time so that will always write a new item, as no item will exist fot that unique id.
I would strongly advise against generating a unique id for the partition key, as it's essentially useless to you.
RestaurantId would be a much better key, you can set the sort key as chequeId to ensure items are unique.
Now you can conditionally put an item for a given restaurant/cheque and your conditions will evaluate correctly as you won't be generating a new item each time.

knexjs and postgres: whereRaw within a join

In the following code I am joining two table and searching for a proper name:
const homesWithUsers = knex('homes')
.join('users', 'homes.id', 'users.home_id')
.whereRaw(
`LOWER("homes.name") LIKE ?`,
'%' + payload.home_name.toLowerCase() + '%'
)
//Stringified
select * from "homes" inner join "users" on "homes"."id" = "users"."home_id" where LOWER("homes.name") LIKE '%george%'
I need to use whereRaw because the database column and the search term are proper names where capitalization is uncertain. (Storing an extra column of the proper names represented in all uppercase is not an option.) However, this query fails with: error: column "homes.name" does not exist. If I remove homes. the query is ambiguous (error: column reference "name" is ambiguous) because both the user and home tables have the columns name.
If I do a simple where statement the query is successful
const homesWithUsers = knex('funeral_homes')
.join('users', 'homes.id', 'users.home_id')
.where({ 'homes.name': payload.home_name })
.select('*');
The only problem is that this will fail with the payload values I expect to field from users interacting with the database.
Any suggestions for how to successfully perform a whereRaw on a joined table?
You need to use identifier replacement syntax ?? when passing column identifiers to raw, which needs to be quotet properly. Like this:
const homesWithUsers = knex('homes')
.join('users', 'homes.id', 'users.home_id')
.whereRaw(
`LOWER(??) LIKE ?`, ["homes.name", '%' + payload.home_name.toLowerCase() + '%']
)

how do i SELECT then parse SQLite row values to assign as variables using Cordova-sqlite-storage plugin

I have a multipage app in Cordova using a (for now local only) SQLite database. All I am wanting to do initially is to use a single row to store 2 different values which I would like to occasionally SELECT, modify, then UPDATE the row with again. I think I am able to SELECT a specific a row but I can't figure out how to parse the two values in the row ready for assigning to variables.
I am using the cordova-sqlite-storage plugin.
var myDB;
/first create/open the database
myDB = window.sqlitePlugin.openDatabase({ name: "mySQLite.db", location: 'default' });
//create table and populate
myDB.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS mcappDB (id text primary key, val1 integer, val2 integer)');
tx.executeSql('INSERT INTO mcappDB VALUES (?,?,?)', ['SessionNums', 12, 15]);
}, function (error) {
alert('Transaction ERROR: ' + error.message);
}, function () {
alert('Table created and populated');
});
//SELECT row and parse (and needing to store parsed data as global variables)
myDB.transaction(function (tx) {
tx.executeSql('SELECT * FROM mcappDB WHERE id="SessionNums"', [],
function (tx, rs) {
alert('Whats in here? ' + rs);
},
function (tx, error) {
alert('select ERROR: ' + error.message);
});
});
Presently, rs just returns as [object Object] and I am unable to parse it. I have tried using rs.toString(0), rs.getString(0), rs.column.item(1), rs(1), etc to no avail.
I in fact began with WHERE id=SessionNums, i.e. no quotes on the row id, but oddly this returned an error with no such columns: SessionNums, tho I thought using the WHERE id= command as such was for fetching row information?! e.g. http://zetcode.com/db/sqlite/select/
Any and all help would be much appreciated.
Cheers, Chris.
First of all, make sure that you have inserted the record before you read it with promises.
Separate insert function and read function and then use this:
$.when(insertFunc()).done(readFunc());
After that you can parse the results as follow:
if (rs.rows.length > 0) {
for (var i = 0; i < rs.rows.length; i++) {
console.log("val1: " + rs.rows.item(i).val1 + "\n" + "val2: " + rs.rows.item(i).val2);
}
}
Best regards,
#BernaAsis

node-mssql Transaction insert - Returning the inserted id..?

I'm using node-mssql 3.2.0 and I need to INSERT INTO a table and return the id of the inserted record.
I can successfully use sql.Transaction() to insert data, but the only parameters given to callbacks (request.query() and transaction.commit()) are:
const request = new sql.Request();
request.query('...', (err, recordset, affected) => {});
const transaction = new sql.Transaction();
transaction.commit((err) => {});
So recordset is undefined for INSERT, UPDATE and DELETE statements, and affected is the number of rows affected, in my case 1.
Does anyone know a good way to obtain an inserted records id (just a primary key id) after a transaction.commit() using node-mssql..?
Instead of just doing an INSERT INTO... statement, you can add a SELECT... statement as well:
INSERT INTO table (...) VALUES (...); SELECT SCOPE_IDENTITY() AS id;
The SCOPE_IDENTITY() function returns the inserted identity column, which means recordset now contains the id:
const request = new sql.Request();
request.query('...', (err, recordset, affected) => {});
I don't think request.multiple = true; is required, because although this includes multiple statements, only one of them is a SELECT... and so returns.
So the answer was SQL related and is not specific to node-mssql.
I know this question has accepted answer.
I made the following way:
let pool = await sql.connect(config);
let insertItem = await pool.request()
.input('ItemId',sql.NVarChar, 'itemId1234')
.input('ItemDesc',sql.NVarChar, 'nice item')
.query("insert into itemTable (Id, ItemId,ItemDesc) OUTPUT INSERTED.ID
values (NEWID(), #ItemId, #ItemDesc);
var insertedItemId = insertItem.recordset[0].ID
This adds unique identifier to data that is saved to db (if table is created so)
create table itemTable(
Id UNIQUEIDENTIFIER primary key default NEWID(),
ItemId nvarchar(25),
ItemDesc nvarchar(25)
)

Categories

Resources