Lately I've been experimenting with building a simple "twitter" app in Postgres by pushing as much logic in the database layer as possible. This includes data validation/sanitization, triggers, and functions.

I needed a way to seed the database with sample data which sometimes required me to specify foreign keys to existing records. I ended up writing a couple plpgsql functions to make this easier.

CREATE FUNCTION random.record(table_name text, exclude uuid DEFAULT uuid_generate_v4())  
  RETURNS record AS $$
    DECLARE
      record record;
    BEGIN
      EXECUTE 'SELECT * FROM ' || table_name || ' WHERE id != $1 ORDER BY random() LIMIT 1'
      INTO record
      USING exclude;

      RETURN record;
    END;
  $$ LANGUAGE plpgsql VOLATILE;

The function above returns a random record from any specied table. It can be called with something like SELECT random.record('users').

It optionally accepts an id to exclude in case you're running a query like:

INSERT INTO followers (follower_id, user_id)  
SELECT id as follower_id, random.id('users', id) as user_id  
FROM users;  

Use this other function if you only need the id: SELECT random.id('users').

CREATE FUNCTION random.id(table_name text, exclude uuid DEFAULT uuid_generate_v4())  
  RETURNS uuid AS $$
    DECLARE
      record record;
    BEGIN
      record := random.record(table_name, exclude);
      RETURN record.id;
    END;
  $$ LANGUAGE plpgsql VOLATILE;

These functions expect your table's primary key to be a uuid called id. You may need to tweak them to match your specific schema if you're using integer or some other primary key column name.

Check out how to use uuids in PostgreSQL if you're not already!