I'm currently working with SQL Server and Sequelize on a project. I'm facing a problem when trying to insert rows in a table that has a trigger associated with it.
I was able to find this information about the problem https://github.com/sequelize/sequelize/issues/3284
I have downloaded the .js files and what it says is that it works with a temp table to overcome this issue:
SequelizeDatabaseError: The target table 'tableA' of the DML statement cannot have any enabled triggers if the statement contains an OUTPUT clause without INTO clause.
This solution is not working for me, I have issues when trying to re use the object that were interseted and can't access to all of the variables.
Is there any other walk around for this issue?
This is my code:
return Person.create( { lastName: options.lastName,
name: options.name,
}, {transaction: t}).then(
function (person) {
return Student.create({ id :person.id,
numberRecord :'PF-'+person.id,
}, {transaction: t}).then(function (student) {
return Shoots.create({ id : person.id,
numberRecord :'PF-'+person.id
}, {transaction: t}).then(function (record) {
return StudentContract.create({
PersonID :person.id,
dateStart:'2016021 00:00:00.000',
endDate:'20161231 00:00:00.000',}
, {transaction: t}).then(function (contract) {
return student;
});
});
});
});
}).then(function (result) {
// Transaction has been committed
// result is whatever the result of the promise chain returned to the transaction callback is
console.log(result);
cb(null, result);
}).catch(function (err) {
// Transaction has been rolled back
// err is whatever rejected the promise chain returned to the transaction callback is
console.error(+err);
cb(err, "Transaction Failed");
});
When using the solution provided in the link above, it says that it can't find the 'id' property. 'id' is defined in Person and Student as the primary key.
Any ideas or official solution from sequelize to work this issue?
Thanks!
Set hasTrigger to true when defining the table, and Sequelize will take care of this for you. For example:
sequelize.define(TABLE_NAME,
{
id: {
type: Sequelize.INTEGER,
allowNull: false,
primaryKey: true
},
description: {
type: Sequelize.VARCHAR(8000)
}
},
{
// options
timestamps: false,
hasTrigger: true
});
I have read your question and I understood that you need to capture what you inserted. And yes it is possible to capture the inserted data with table variable.
Try below, hope it will help atleast to get some other idea.
DECLARE #IDENTITY_CAPTURE TABLE (INSERTED_IDENTITY BIGINT, INSERTED_BASE_NME VARCHAR(20))
INSERT INTO SALESORDER
OUTPUT INSERTED.SALESORDER_NBR, INSERTED.SALESORDER_NME INTO #IDENTITY_CAPTURE
SELECT 1, 'PICSART'
UNION ALL
SELECT 2, 'IMAX'
Then you can query on Table variable to get the data inserted.
Thank you
Related
I'm trying to do the following using Prisma:
If a category row with the same hash and user_id I have exists, just update it's "name" field, otherwise, create the row
Is this possible? TS is giving me an error saying that the type of the key given on "where" has to be of categoriesWhereUniqueInput, yet neither hash nor user_id are unique, they can repeat, it's the combination between the two that's gonna be unique
How can I work around this? Do I have to manually check if there's an id and update/create based on that?
Thanks a lot in advance!
const category = await prisma.categories.upsert({
where: {
hash,
user_id: id,
},
update: {
name,
},
create: {
hash,
name,
user_id: id,
},
});
When a combination of fields is unique, Prisma will generate a new type for the where condition which is basically just the name of all the relevant fields appended together with _.
Take a look at the categoriesWhereUniqueInput to see what the name is. Most likely it is called user_id_hash or hash_user_id.
This is what the query will look like, roughly speaking:
const category = await prisma.categories.upsert({
where: {
user_id_hash: { // user_id_hash is the type generated by Prisma. Might be called something else though.
user_id: 1,
hash: "foo"
}
},
update: {
name: "bar",
},
create: {
hash: "foo",
name: "bar",
user_id: 1,
},
})
Im trying to update a value in a nested Array in a mongoose schema using express. I have the code required in place what i figuered i needed to update it, but the array doesn't get updated.
So the idea is to be able to have an array of data base schema objects with two fields, schemaName and schemaFields. I want to be able to update (add/remove)the values from schemaFields field of a specific schema object as needed.
I've already tried a bunch of stuff on here and elsewhere on the internet but nothing appears to work. I tried using findOneAndUpdate, findByIdAndUpdate etc.
My mongoose schema is as follows,
let databaseSchema = new Schema({
schemaName: { type: String },
schemaFields: [String]
});
let databaseSchemas = new Schema(
{
dbSchemas: [databaseSchema]
},
{
collection: 'databaseSchemas'
}
);
my update function is as follows,
schemasModel.mongo
.update(
{
_id: req.body.documentId,
'dbSchemas._id': req.body.schemaId
},
console.log('preparin to push the field \n'),
{
$push: {
'dbSchemas.$.schemaFields': req.body.newField
}
}
)
.then(() => {
res.send('new field added successfully');
});
So I solved it by removing the console.log() as a second argument to the model.update() function. Apparently this has to be the object with the operation.
The working code for the Model.update function is as follows,
schemasModel.mongo
.update(
{
_id: req.body.documentId,
'dbSchemas.schemaName': req.body.schemaToSearch
},
{
$push: {
'dbSchemas.$.schemaFields': req.body.newField
}
}
)
.then(() => {
res.send('new field added successfully');
});
I have a SQL server database with a table which auto inserts a guid in each row when a record is added. This column is the primary key for the table and never needs a value to be supplied to it as it's automatic.
The trouble is that Sequelize is sending NULL for this column every time I do a .create({emailAddress:"test#test.com"}) call which is causing an error in the database (because nulls aren't allowed, obviously).
I've tried adding omitNull at the top level and at the "call" level and neither of them work , unless I remove the primary key and then it doesn't send a NULL. So it seems that Sequelize thinks that if something is the primary key then it must send a value, not understanding that the SQL SERVER database is going to handle insertion of that value.
Anybody know a workaround?
// Model
module.exports = function (sequelize, DataTypes) {
const Player = sequelize.define('Player', {
playerId: {
primaryKey: true,
type: DataTypes.STRING
},
emailAddress: {
type: DataTypes.STRING
}
}, {
timestamps: false
});
return Player;
};
// Create a row
let newPlayer = {
emailAddress:'test#test.com'
}
Player.create(newPlayer, {omitNull:true}).then(function(player){
console.log("player", player)
}).catch(function(error){
console.log("error", error)
})
Adding defaultValue and allowNull should do the job
playerId: {
primaryKey: true,
defaultValue: '',
allowNull: false,
}
How could I find an image by id in this Schema. I have the id of the User and the id of the image I am looking for. What would be the best way to do this and do all images in this case have different ids or could they have the same id because they don't belong to the same User?
My Schema looks like this:
var userSchema = new Schema({
local: {
email: String,
password: String
},
facebook: {
id: String,
token: String,
email: String,
name: String
},
name: String,
about: String,
images: [{
id: Schema.ObjectId,
link: String,
main: Boolean
}]
});
When you are interested in the full object it is a simple find:
.find({"facebook.id":"<id>", "images.id":<image-id>})
I don't think that there is a way to reduce the image array in the result.
To update a single element in the image array you can use this:
.update({"facebook.id":"<id>", "images.id":<image-id>}, {$set : {"images.$.main" :false} } );
userSchema .find({facebook.id: "some ID",{ "images.id": { $in: [ id1, id2, ...idn] }}
since images are inside the document you can have same ID's however every time you query you should keep in mind that you send some other parameters such as facebook.id or facebook.email along with image id's to retrieve them. Otherwise you end up getting all that might be irrelevant only because you decide to keep same ID's for images.
tl;dr
I struggled with this and came up with a solution. Like you, I was trying to query for a deeply nested object by the _id, but I kept coming up empty with the results. It wasn't until I did some type checking that I realized the id value I was getting from my frontend, while directly supplied by mongoose, was in fact a String and not an Object.
I realize this question was already partially answered before, but that person's solution didn't work for me, and the comment on the answer tells me you wanted to update the specific image you queried for, which is exactly what I was trying to do.
The solution
In order to select an object from the nested array by the _id value, first you'll have to install the npm package bson-objectid and use the provided method to convert your string into an objectId in your query.
In your terminal:
npm i bson-objectid
In your code:
const ObjectId = require('bson-objectid')
userSchema.findOneAndUpdate(
{ "facebook.id": <user-id>, "images._id": ObjectId(<image-id>) },
{ "$set": { "images.$.main": false } },
{ new: true }, // an extra options parameter that returns the mutated document
(err, user) => {
if (err) {
handleErr(err)
} else {
console.log(user)
// do something with new user info
}
)
I have a question about how to just get a certain element of an array using MongoDB and MeteorJS. I have the following schema for the user document:
bankList:[
{
id: "34567890987654345678",
name: "xfgchjbkn",
type: "credit"
},
{
id: "09876543456789098767"
name: "65789876t8",
type: "debit"
}
]
I first subscribe to only part of the fields in the array, specifically I gather a list of all the ids. Then I have an edit screen that should subscribe to all of the fields for a specific element in the array with a matching id. I do not want to expose the rest of the array just the single element. Currently, I use the following to first gather a list of just the ids:
Meteor.users.find({_id: this.userId},
{fields:{'bankList.id': 1}});
And the following publication-subscription method to get just a specific element's information:
Publication:
Meteor.publish("userBankAdvanced", function(bankId){
check(bankId,String);
if(this.userId){
return Meteor.users.find({_id:this.userId,"bankList.id": bankId}, {'bankList.$': 1});
}else{
this.ready();
}
});
Subscription:
this.route('edit_account', {
path: '/edit/account/',
waitOn: function(){
if(Session.get("bankId")){
return Meteor.subscribe('userBankAdvanced',Session.get("bankId"));
}
return null;
},
data: function(){
if(Session.get("bankId")){
return Meteor.users.findOne();
}
return null;
},
onBeforeAction: function(){
beforeHooks.isRevise(Session.get("bankId"));
}
});
The subscription method returns all of the elements of the array with all of the information.
I want, for example, just this (not the entire list with all of the information):
bankList:[
{
id: "34567890987654345678",
name: "xfgchjbkn",
type: "credit"
}]
It looks like you're just missing the "fields" specifier in your "userBankAdvanced" publish function. I wrote a test in meteorpad using your example and it seems to work fine. The bank id is hardcoded for simplicity there.
So instead of
return Meteor.users.find({_id:this.userId,"bankList.id": bankId}, {'bankList.$': 1});
try using
return Meteor.users.find({_id:this.userId,"bankList.id": bankId}, {fields: {'bankList.$': 1}});
No luck, in meteor the "fields" option works only one level deep. In other words there's no builtin way to include/exclude subdocument fields.
But not all is lost. You can always do it manually
Meteor.publish("userBankAdvanced", function (bankId) {
var self = this;
var handle = Meteor.users.find({
_id: self.userId, "bankList.id": bankId
}).observeChanges({
added: function (id, fields) {
self.added("users", id, filter(fields, bankId));
},
changed: function (id, fields) {
self.changed("users", id, filter(fields, bankId));
},
removed: function (id) {
self.removed("users", id);
},
});
self.ready();
self.onStop(function () {
handle.stop();
});
});
function filter(fields, bankId) {
if (_.has(fields, 'bankList') {
fields.bankList = _.filter(fields.bankList, function (bank) {
return bank.id === bankId;
});
}
return fields;
}
EDIT I updated the above code to match the question requirements. It turns out though that the Carlos answer is correct as well and it's of course much more simple, so I recommend using that one.