Saya membuat klon Twitter menggunakan MySQL dan saya sedang menulis prosedur tersimpan untuk memperbarui tabel umpan pengguna dari pengguna yang baru saja mengikuti seseorang yang baru untuk memasukkan semua tweet dari orang yang telah diikuti pengguna.

CREATE PROCEDURE `populate_userfeed_after_following`(IN username varchar(20), IN following_username varchar(20))
BEGIN
    DECLARE last_tweet timestamp default null;
    DECLARE following_id int;
    
    SELECT id from users where username=following_username into following_id;
    
    SET @timestamp_tweet = CONCAT('SELECT timestamp FROM userfeed_', username, ' ORDER BY timestamp DESC LIMIT 1 into', last_tweet);
    
    PREPARE timestamp_tweetQuery FROM @timestamp_tweet;
    EXECUTE timestamp_tweetQuery;
    
    IF (last_tweet is NULL) THEN
        SET @insert_statement = CONCAT('INSERT INTO userfeed_', username, '(tweet_id) SELECT id from tweets
        WHERE author=', following_id,
        ' LIMIT 200');
    ELSE
        SET @insert_statement = CONCAT('INSERT INTO userfeed_', username, '(tweet_id) SELECT id from tweets
        WHERE author=', following_id ,'and timestamp >', last_tweet);
    END IF;
    
    PREPARE insertQuery FROM @insert_statement;
    EXECUTE insertQuery; 
    
    DEALLOCATE PREPARE timestamp_tweetQuery;
    DEALLOCATE PREPARE insertQuery;
    
END

Saya menyimpan stempel waktu yang paling kedaluwarsa dalam variabel lokal bernama last_tweet setelah mengambilnya dari tabel umpan pengguna dari pengguna yang mengikuti seseorang dan yang saya periksa menjadi NULL untuk dibuat pernyataan sisipan dinamis.

Setiap kali saya memanggil prosedur dengan melewati parameter, mis.,

call populate_userfeed_after_following('joe', 'rocky'); 
#joe follows rocky

Saya mendapatkan kesalahan,

Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1

Saya akan sangat menghargai jika Anda menunjukkan kesalahan dalam kode saya.

0
realj4ke 19 November 2020, 20:22

1 menjawab

Jawaban Terbaik

Seperti yang ditunjukkan oleh @P.Salmon, penggunaan variabel lokal (menggunakan pernyataan DECLARE) tidak akan berfungsi dalam situasi ini. Jadi saya mengoreksi kode untuk menggunakan variabel sesi atau variabel yang ditentukan pengguna (menggunakan pernyataan SET) dan menulis ulang.

Logika berikut berfungsi:

CREATE PROCEDURE `populate_userfeed_after_following`(IN username varchar(20), IN following_username varchar(20))
BEGIN
    -- DECLARE last_tweet timestamp default null;
    -- DECLARE following_id int;
    
    SET @following_id = 0;
    SET @last_tweet = NULL;
    
    SET @followingId_tweet = CONCAT('SELECT id from users where username=\'', following_username, '\' into @following_id');
    SET @timestamp_tweet = CONCAT('SELECT timestamp FROM userfeed_', username, ' ORDER BY timestamp DESC LIMIT 1 into @last_tweet');
    
    PREPARE followingIdQuery FROM @followingId_tweet;
    EXECUTE followingIdQuery; 
    DEALLOCATE PREPARE followingIdQuery;
    
    PREPARE timestamp_tweetQuery FROM @timestamp_tweet;
    EXECUTE timestamp_tweetQuery; 
    DEALLOCATE PREPARE timestamp_tweetQuery;
    
    IF (@last_tweet is NULL) THEN
        SET @insert_statement = CONCAT('INSERT INTO userfeed_', username, '(tweet_id) SELECT id from tweets
        WHERE author=@following_id
        LIMIT 200');
    ELSE
        SET @insert_statement = CONCAT('INSERT INTO userfeed_', username, '(tweet_id) SELECT id from tweets
        WHERE author=@following_id and timestamp > @last_tweet');
    END IF;
    
    PREPARE insertQuery FROM @insert_statement;
    EXECUTE insertQuery; 
    DEALLOCATE PREPARE insertQuery;
    
END

Kesalahan awal disebabkan oleh pernyataan pilih di mana saya menggunakan nilai yang diteruskan dalam parameter untuk membuat pernyataan SQL dinamis dan baris di bawahnya tempat SET @timestamp_tweet digunakan. Cara yang benar untuk melakukannya adalah dengan menggunakan pernyataan yang sudah disiapkan.

0
realj4ke 20 November 2020, 10:15