Mysql integrity error 1452 on insert - mysql

select * from memory_games_game; gives me following table:
select * from memory_games_game_state;gives me following table:
I have a stored proc as bellow:
delimiter //
CREATE PROCEDURE get_game_by_user_id(
p_user_id int, p_game_id int
)
BEGIN
insert into memory_games_game_state(user_id, game_id, level, progress)
SELECT 24 as user_id,
game.game_type as game_id,
1 as level,
0 as progress
FROM memory_games_game game
left outer join memory_games_game_state gameState on
game.game_type=gameState.game_id and
gameState.user_id=24
where game.level=1 and gameState.user_id is null;
if p_game_id = -1 then
SELECT gameState.level, game_type, `current_date`
FROM memory_games_game game join memory_games_game_state gameState on
game.game_type=gameState.game_id and
gameState.user_id=24 and
game.level=gameState.level;
else
SELECT gameState.level, game_type, `current_date`
FROM memory_games_game game join memory_games_game_state gameState on
game.game_type=gameState.game_id and
gameState.user_id=p_user_id and
game.level=gameState.level
WHERE game_type=12;
end if;
END
//
The first insert inserts the records into memory_games_game_statetable.
This insert is successful for game_id from 8 to 11 however, it fails for 12 with following error:
I am able to insert records in table memory_games_gamefor game_type 12 which is nothing but game_id in the other table i.e. memory_games_game_state
What's going wrong?
UPDATE:
My django models:
class Game(models.Model):
#Field for storing game type
GAME_TYPE_CHOICES = (
(8, 'Simon Game'),
(9, 'Pinpoint reaction'),
(10, 'Loslassen'),
(11, 'Word pair'),
(12, 'Wortschatz')
)
game_type = models.IntegerField(choices=GAME_TYPE_CHOICES)
level = models.IntegerField(default='1')
#This helps to print in admin interface
def __str__(self):
return u"%s level %s" % (self.get_game_type_display(), self.level)
class Game_state(models.Model):
game = models.ForeignKey(Game, blank=True, null=True)
user = models.ForeignKey(User, blank=True, null=True)
level = models.IntegerField(default='1')
progress = models.IntegerField(default='0')
current_date = models.DateField(auto_now=True)
class Game_state_ui_model(models.Model):
GAME_TYPE_CHOICES = (
(8, 'Simon Game'),
(9, 'Pinpoint reaction'),
(10, 'Loslassen'),
(11, 'Word pair'),
(12, 'Wortschatz')
)
game_type = models.IntegerField(choices=GAME_TYPE_CHOICES)
level = models.IntegerField()
user_id = models.IntegerField(default='0')
current_date = models.DateField(auto_now=True)
# static method to fetch games for a paricular user
#staticmethod
def fetch_games(user_id, game_id):
print("Fetching games in model")
# create a cursor
cur = connection.cursor()
# execute the stored procedure passing in
# search_string as a parameter
cur.callproc('get_game_by_user_id', [user_id, game_id,])
# grab the results
results = cur.fetchall()
cur.close()
Game_state_list=[]
for row in results:
print("Get game", row)
Gs = Game_state_ui_model()
Gs.level=row[0]
Gs.game_type=row[1]
Gs.current_date=row[2]
Game_state_list.append(Gs)
return Game_state_list

As the error states, game_id references memory_games_game.id; NOT memory_games_game.game_type.
The thinking that "game_type 12 which is nothing but game_id in the other table i.e. memory_games_game_state" is incorrect.
You need a row in memory_games_game with id = 12.

I dropped all the tables and did migration again, which somehow solved the problem. I didn't change anything else.

Related

Order of INSERT or UPDATE in a transaction in binlog

I'm using debezium connector to stream my Mysql binlog change records to Kafka Topic. My transaction is like so:
Tx begin
Insert INTO Project(Name, InProgress) VALUES ('New Project', 0);
-- We get the created id (say PID)
Insert INTO Tasks(TaskName, ProjectID) VALUES ('Task A', PID);
-- We get the taskID (say TID1)
Insert INTO Tasks(TaskName, ProjectID) VALUES ('Task B', PID);
-- We get the taskID (say TID2)
UPDATE Tasks SET TaskName = 'Task C' where ID = TID2;
Update Project SET InProgress = 1 where ID = PID;
Tx end
My question is in what order will I get the bin log records? Will I get the records in the order in which the records are inserted? So like this?
NEW Project with ID = PID
NEW Task with ID = TID1
NEW Task with ID = TID2
Is this documented anyplace?

SQL Alchemy, how to insert data into two tables and reference foreign key?

I am inserting a list of python dictionaries into a Postgres database using SQL Alchemy (via Flask_sqlalchemy).
One of the tables is a list of all unique items (table 1), while the second is a time series of data related to an item (table2).
In essence, I want to insert any new row (with unique hash) in to table 1, then insert it's data to table 2. If it already exists in table 1, just insert the "child" in table 2 referencing the entry in table 1.
This is one item in the list, the list has a few hundred of these.
{'placement': '5662448s608653114', 't1': datetime.datetime(2018, 4, 15, 17, 47, 7, 434982), 't2': datetime.datetime(2018, 4, 25, 17, 47, 7, 434994), 'camp_id': 1, 'clicks': '0', 'visits': '3', 'conversions': '0', 'revenue': '0'}
I would like to insert 5662448s608653114 into table1, and then insert all the other data into table2, where i reference the item not by 5662448s608653114, but by it's id in table 1
So I'd get:
Table 1:
____________________
1| 5662448s608653114
2| 5520103
Table 2:
ID | Pl id | T1 | T2 | cost | revenue | clicks
_______________________________________________
499| 1 |
500| 2 |
I tested this, which does not work:
def write_tracker_data(self):
for item in self.data:
ts = Placements(placement_ts_hash=item["placement"])
pl = TrackerPlacementData(placement_id=ts.id, t1=item["t1"], t2=item["t2"], camp_id=1, revenue=item["revenue"], clicks=item["clicks"], conversions=item["conversions"])
db.session.add(pl)
db.session.commit()
The above code inserts the data, but with none instead of the id from the Table 1. It also doesn't seem very efficient, you know that feeling when something can definitely be done a better way ...
Here's the model classes for reference:
class Placements(db.Model):
id = db.Column(db.Integer, primary_key=True)
traffic_source = db.Column(db.Integer, db.ForeignKey('ts_types.id'))
placement_ts_hash = db.Column(db.String, index=True)
placement_url = db.Column(db.String)
placement_type = db.Column(db.String)
# Relationship betwwen unique placement table and tracker_placeemnt_data
tracker_data = db.relationship("TrackerPlacementData", backref="placement_hash")
class TrackerPlacementData(db.Model):
id = db.Column(db.Integer, primary_key=True)
t1 = db.Column(db.DateTime(timezone=True))
t2 = db.Column(db.DateTime(timezone=True), index=True)
camp_id = db.Column(db.Integer, db.ForeignKey('campaigns.id'), nullable=False)
placement_id = db.Column(db.Integer, db.ForeignKey('placements.id'), nullable=True, index=True)
revenue = db.Column(db.Float)
clicks = db.Column(db.Integer)
conversions = db.Column(db.Integer)
Thanks in advance.
Edit: This works, but it doesn't seem very good due to a new session for every item in the loop :/
def write_tracker_data(self):
for item in self.data:
ts = Placements(placement_ts_hash=item["placement"])
db.session.add(ts)
db.session.commit()
pl = TrackerPlacementData(placement_hash=ts, t1=item["t1"], t2=item["t2"], camp_id=1,
revenue=item["revenue"], clicks=item["clicks"], conversions=item["conversions"])
db.session.add(pl)
db.session.commit()
Your Placement instance won't have an id until it is committed. This is where the tracker_data relationship can help you...
for item in self.data:
ts = Placements(placement_ts_hash=item["placement"])
pl = TrackerPlacementData(
t1=item["t1"],
t2=item["t2"],
camp_id=1,
revenue=item["revenue"],
clicks=item["clicks"],
conversions=item["conversions"]
)
ts.tracker_data.append(pl)
db.session.add(ts)
db.session.commit()
Notice that pl.placement_id is not set to anything. Instead pl is appended to ts.tracker_data and everything should be looked after for you when you call commit.

How to update multiple rows in MySQL by one line?

I have PHP array with data.
Now, i'm using a cycle like this:
$updArray = array(1=>11,2=>12,3=>13);
foreach($updArray as $id=>$value)
{
$query = "UPDATE table1 SET column1='$value' WHERE cart_id = '$id'";
mysql_query($query,$link);
}
I think, if array contains thousands rows, it would be slow.
Is there a way to update MySQL table (apply my data from array) without cycle and updating every row?
You can try building a single update with a CASE statement, like so:
UPDATE table1
SET column1 = CASE
WHEN cart_id = 1 THEN 11
WHEN cart_id = 2 THEN 12
...
ELSE cart_id = cart_id
END
INSERT INTO students
(id, score1, score2)
VALUES
(1, 5, 8),
(2, 10, 8),
(3, 8, 3),
(4, 10, 7)
ON DUPLICATE KEY UPDATE
score1 = VALUES(score1),
score2 = VALUES(score2);

Django mysql tuple index out of range

My views.py looks like following:
#api_view(('GET',))
def save_progress_for_particular_user(request, exerciseId, rating):
#view to call stored proc that stores the progress for a particular user
#save_progress(user_id,exercise_id,rating,date)
result=Exercise_progress_model.save_progress_for_particular_user(
request.user.id, exerciseId, rating, datetime.date.today())
serializer = ExerciseProgressSerializer(result, many=True)
return Response(serializer.data)
My models.py looks like following:
class Exercise_progress_model(models.Model):
# Model that will be rendered on the UI
#Field for storing intensity level
INTENSITY_LEVEL_CHOICES = (
(1, 'Really simple'),
(2, 'Rather Simple'),
(3, 'Simple'),
(4, 'Okay'),
(5, 'Difficult'),
(6, 'Rather Difficult'),
(7, 'Really Difficult'),
)
intensity_level = models.IntegerField(choices=INTENSITY_LEVEL_CHOICES)
#Field for storing progress
progress = models.IntegerField(default='0')
#Field for storing exercise type
EXERCISE_TYPE_CHOICES = (
(1, 'Best stretch'),
(2, 'Butterfly reverse'),
(3, 'Squat row'),
(4, 'Plank'),
(5, 'Push up'),
(6, 'Side plank'),
(7, 'Squat'),
)
exercise_id = models.IntegerField(choices=EXERCISE_TYPE_CHOICES)
#Field for storing current date
current_date = models.DateField()
#Field for storing user rating
user_rating = models.IntegerField(default='0')
# static method to save progress for a particular user
#staticmethod
def save_progress_for_particular_user(user_id, exercise_id, rating, date):
# create a cursor
cur = connection.cursor()
# execute the stored procedure passing in
# search_string as a parameter
cur.callproc('save_exercise_state', [user_id, exercise_id, rating, date,])
# grab the results
result = cur.fetchall()
cur.close()
User_progress_list = []
for row in result:
Epm = Exercise_progress_model()
Epm.intensity_level=row[0]
Epm.progress=row[1]
Epm.exercise_id=row[2]
Epm.user_rating=row[3]
Epm.current_date=row[4]
User_progress_list.append(Epm)
return User_progress_list
My serializers.py looks like following:
class ExerciseProgressSerializer(serializers.Serializer):
intensity_level = serializers.IntegerField(required=True)
progress = serializers.IntegerField(required=True)
exercise_type = serializers.IntegerField(required=True)
user_rating = serializers.IntegerField(required=True)
current_date = serializers.DateField()
My stored procedure looks like following:
delimiter //
CREATE PROCEDURE save_exercise_state(
p_user_id int, p_exercise_id int, p_rating int, p_date date
)
BEGIN
DECLARE lv_current_intensity, lv_progress, lv_final_intensity int;
DECLARE lv_date date;
select intensity_level into lv_current_intensity
from demo_exercise_state where
user_id=p_user_id and exercise_id=p_exercise_id;
select progress into lv_progress
from demo_exercise_state where
user_id=p_user_id and exercise_id=p_exercise_id;
select current_date into lv_date
from demo_exercise_state where
user_id=p_user_id and exercise_id=p_exercise_id;
select lv_progress, lv_current_intensity, lv_date;
If lv_date=p_date then
select "OK";
end if;
if p_rating=0 then
set lv_progress=lv_progress;
elseif p_rating=1 then
if lv_progress=3 then
set lv_progress=0;
if lv_current_intensity = 7 then
set lv_final_intensity = 7;
else
set lv_final_intensity = lv_current_intensity + 1;
end if;
else
if lv_current_intensity=7 then
set lv_progress=0;
set lv_final_intensity=lv_current_intensity;
else
set lv_progress=lv_progress+1;
set lv_final_intensity=lv_current_intensity;
end if;
end if;
elseif p_rating =-1 then
if lv_progress=0 then
if lv_current_intensity = 1 then
set lv_final_intensity = 1;
set lv_progress=0;
else
set lv_final_intensity = lv_current_intensity - 1;
set lv_progress=3;
end if;
else
set lv_progress=lv_progress-1;
set lv_final_intensity=lv_current_intensity;
end if;
end if;
Update demo_exercise_state
SET progress = lv_progress,
intensity_level = lv_final_intensity,
`current_date` = p_date,
user_rating = p_rating
WHERE user_id = p_user_id AND exercise_id = p_exercise_id;
SELECT intensity_level, progress, exercise_id, user_rating , current_date
FROM demo_exercise_state
WHERE user_id = p_user_id AND exercise_id = p_exercise_id AND user_rating=p_rating;
END
//
Screenshot of the result of executing this proc for
call save_exercise_state(4,1,1,curdate()); is as following
When I call this view I get tuple index out of range error for the line Epm.user_rating=row[3].
What is the reason for this? Is there any workaround?

MySQL Error: 1305. Stored Procedures

I'm getting
Error Code: 1305. FUNCTION acdb_extended.player does not exist
When I attempt to call a stored procedure. The odd thing about the error is that "player" isn't the name of the stored procedure.
Here's the stored procedure code, there is probably a number of things wrong with it but it's correct as far as I can tell:
CREATE PROCEDURE `acdb_extended`.`addAllianceMember` (IN accountNumber VARCHAR(255),
IN userName VARCHAR(255), IN serverInitial CHAR(1), IN galaxy TINYINT(2),
IN region TINYINT(2), IN system TINYINT(2), IN astro TINYINT(2), IN level TINYINT(2))
BEGIN
IF player (account_number) = accountNumber
THEN REPLACE INTO player (username)
VALUES (userName);
ELSE INSERT INTO player (account_number, username)
VALUES (accountNumber, userName);
END IF;
IF coordinates (server_initial) = serverInitial AND
coordinates (galaxy) = galaxy AND
coordinates (region) = region AND
coordinates (system) = system AND
coordinates (astro) = astro
THEN REPLACE INTO coordinates (player_ID)
VALUES ((SELECT player_ID FROM player WHERE username = userName));
ELSE INSERT INTO coordinates (player_ID, server_initial, galaxy, region, system, astro)
VALUES ((SELECT player_ID FROM player WHERE username = userName), serverInitial,
galaxy, region, system, astro);
END IF;
IF jumpgate (player_ID) = (SELECT player_ID FROM player WHERE username = userName) AND
jumpgate (coordinates_ID) = (SELECT c.coordinates_ID FROM coordinates c, player p WHERE c.player_ID = p.player_ID
AND p.username = userName)
THEN REPLACE INTO jumpgate (level)
VALUES (level);
ELSE INSERT INTO jumpgate (player_ID, coordinates_ID, level, usable)
VALUES ((SELECT player_ID FROM player WHERE username = userName),
(SELECT c.coordinates_ID FROM coordinates c, player p WHERE c.player_ID = p.player_ID
AND p.username = userName), level, TRUE);
END IF;
END
And here is the SQL statement I'm using to test it:
CALL addAllianceMember(8494618, 'Carl', 'G', 29, 08, 10, 01, 04);
Any hints on where this is going wrong?
in this line
IF player (account_number) = accountNumber
it's calling player like a function, it's look like player doesn't exists as a function.
Here you have used Player as function just after BEGIN.
BEGIN
IF player (account_number) = accountNumber