case statement within insert

Started by tango wardalmost 8 years ago8 messagesgeneral
Jump to latest
#1tango ward
tangoward15@gmail.com

I want to insert data from mysql into a table in postgresql. I want to
check when the subjectcode contains PE or NSTP so I can assign True or
False to another column in destination DB.

# Source data:

# Source data: MySQL
curr_msql.execute(''' SELECT code, subjectname
FROM test_subj ''')

# Destination
for row in curr_msql:
curr_psql.execute(''' INSERT INTO subs (
created, modified,
subjcode, subjname,
is_pe_or_nstp)

VALUES (current_timestamp,
current_timestamp,
%s, %s,
CASE
WHEN code like '%%PE%%' or code like '%%NSTP%%'
THEN True
ELSE False
END) ''', (row['code'], row['subjectname']))

I am getting TypeError: not all arguments converted during string
formatting.

Any advice pls?

#2David G. Johnston
david.g.johnston@gmail.com
In reply to: tango ward (#1)
Re: case statement within insert

On Friday, May 25, 2018, tango ward <tangoward15@gmail.com> wrote:

WHEN code like '%%PE%%' or code like '%%NSTP%%'

I am getting TypeError: not all arguments converted during string
formatting.

Any advice pls?

Unclear how to inject percent signs in the query string here. I'd just
avoid them and use regular expressions.

David J.

#3Adrian Klaver
adrian.klaver@aklaver.com
In reply to: tango ward (#1)
Re: case statement within insert

On 05/25/2018 02:04 AM, tango ward wrote:

I want to insert data from mysql into a table in postgresql. I want to
check when the subjectcode contains PE or NSTP so I can assign True or
False to another column in destination DB.

# Source data:

 # Source data: MySQL
   curr_msql.execute(''' SELECT code, subjectname
                          FROM test_subj ''')

# Destination
for row in curr_msql:
            curr_psql.execute(''' INSERT INTO subs (
                                                    created, modified,
                                                    subjcode, subjname,
                                                    is_pe_or_nstp)

                                  VALUES (current_timestamp,
current_timestamp,
                                          %s, %s,
                                          CASE
        WHEN code like '%%PE%%' or code like '%%NSTP%%'

Shouldn't the above be?:

subjcode like '%%PE%%' or subjcode like '%%NSTP%%'

        THEN True
        ELSE False
    END) ''', (row['code'], row['subjectname']))

I am getting TypeError: not all arguments converted during string
formatting.

Any advice pls?

--
Adrian Klaver
adrian.klaver@aklaver.com

#4Adrian Klaver
adrian.klaver@aklaver.com
In reply to: Adrian Klaver (#3)
Re: case statement within insert

On 05/25/2018 06:52 AM, Adrian Klaver wrote:

On 05/25/2018 02:04 AM, tango ward wrote:

I want to insert data from mysql into a table in postgresql. I want to
check when the subjectcode contains PE or NSTP so I can assign True or
False to another column in destination DB.

# Source data:

  # Source data: MySQL
    curr_msql.execute(''' SELECT code, subjectname
                           FROM test_subj ''')

# Destination
for row in curr_msql:
             curr_psql.execute(''' INSERT INTO subs (
                                                     created, modified,
                                                     subjcode, subjname,
                                                     is_pe_or_nstp)

                                   VALUES (current_timestamp,
current_timestamp,
                                           %s, %s,
                                           CASE
         WHEN code like '%%PE%%' or code like '%%NSTP%%'

Shouldn't the above be?:

subjcode like '%%PE%%' or subjcode like '%%NSTP%%'

Turns out that won't work as you cannot refer to a column in the CASE:

cur.execute("insert into cell_per(category, cell_per, season,
plant_type, short_category) values('herb test', 1, 'annual', CASE WHEN
category like '%%herb%%' THEN 'herb' ELSE 'flower' END, 'ht' )")

ProgrammingError: column "category" does not exist
LINE 1: ...gory) values('herb test', 1, 'annual', CASE WHEN category l...
^
HINT: There is a column named "category" in table "cell_per", but it
cannot be referenced from this part of the query.

This works:

cur.execute("insert into cell_per(category, cell_per, season,
plant_type, short_category) values(%s, 1, 'annual', CASE WHEN %s like
'%%herb%%' THEN 'herb' ELSE 'flower' END, 'ht' )", ('herb test', 'herb
test'))

So change code to row['code']?

         THEN True
         ELSE False
     END) ''', (row['code'], row['subjectname']))

I am getting TypeError: not all arguments converted during string
formatting.

Any advice pls?

--
Adrian Klaver
adrian.klaver@aklaver.com

#5Adrian Klaver
adrian.klaver@aklaver.com
In reply to: Adrian Klaver (#4)
Re: case statement within insert

On 05/25/2018 07:05 AM, Adrian Klaver wrote:

On 05/25/2018 06:52 AM, Adrian Klaver wrote:

On 05/25/2018 02:04 AM, tango ward wrote:

I want to insert data from mysql into a table in postgresql. I want
to check when the subjectcode contains PE or NSTP so I can assign
True or False to another column in destination DB.

# Source data:

  # Source data: MySQL
    curr_msql.execute(''' SELECT code, subjectname
                           FROM test_subj ''')

# Destination
for row in curr_msql:
             curr_psql.execute(''' INSERT INTO subs (
                                                     created, modified,
                                                     subjcode, subjname,
                                                     is_pe_or_nstp)

                                   VALUES (current_timestamp,
current_timestamp,
                                           %s, %s,
                                           CASE
         WHEN code like '%%PE%%' or code like '%%NSTP%%'

Shouldn't the above be?:

subjcode like '%%PE%%' or subjcode like '%%NSTP%%'

Turns out that won't work as you cannot refer to a column in the CASE:

cur.execute("insert into  cell_per(category, cell_per, season,
plant_type, short_category)  values('herb test', 1, 'annual', CASE WHEN
category like '%%herb%%' THEN 'herb' ELSE 'flower' END, 'ht' )")

ProgrammingError: column "category" does not exist
LINE 1: ...gory)  values('herb test', 1, 'annual', CASE WHEN category l...
                                                             ^
HINT:  There is a column named "category" in table "cell_per", but it
cannot be referenced from this part of the query.

This works:

cur.execute("insert into  cell_per(category, cell_per, season,
plant_type, short_category)  values(%s, 1, 'annual', CASE WHEN %s like
'%%herb%%' THEN 'herb' ELSE 'flower' END, 'ht' )", ('herb test', 'herb
test'))

So change code to row['code']?

Insufficient caffeine.

...
WHEN %s like '%%PE%%' or %s like '%%NSTP%%'

...
, (row['code'], row['subjectname'], row['code'], row['code'])

FYI this is why I like the named parameters then the above could be
shortened to:

{'code': row['code'], 'subjectname': row['subjectname']}

and you get clearer query code:

VALUES (current_timestamp, current_timestamp,
%(code)s, %(subjectname)s,
CASE
WHEN %(code)s like '%%PE%%' or %(code)s like '%%NSTP%%'
THEN True
ELSE False
END)

         THEN True
         ELSE False
     END) ''', (row['code'], row['subjectname']))

I am getting TypeError: not all arguments converted during string
formatting.

Any advice pls?

--
Adrian Klaver
adrian.klaver@aklaver.com

#6Francisco Olarte
folarte@peoplecall.com
In reply to: tango ward (#1)
Re: case statement within insert

On Fri, May 25, 2018 at 11:04 AM, tango ward <tangoward15@gmail.com> wrote:

CASE
WHEN code like '%%PE%%' or code like '%%NSTP%%'
THEN True
ELSE False

I cannot advise you on the %% stuff, which I do not totally understand, but

CASE WHEN condition THEN true ELSE false END

when contition is ( as it should in a CASE ) a boolean expression is a
classic antipattern , just use 'condition' or '(condition)'

Francisco Olarte.

#7tango ward
tangoward15@gmail.com
In reply to: Adrian Klaver (#5)
Re: case statement within insert

On Fri, May 25, 2018 at 10:19 PM, Adrian Klaver <adrian.klaver@aklaver.com>
wrote:

On 05/25/2018 07:05 AM, Adrian Klaver wrote:

On 05/25/2018 06:52 AM, Adrian Klaver wrote:

On 05/25/2018 02:04 AM, tango ward wrote:

I want to insert data from mysql into a table in postgresql. I want to
check when the subjectcode contains PE or NSTP so I can assign True or
False to another column in destination DB.

# Source data:

# Source data: MySQL
curr_msql.execute(''' SELECT code, subjectname
FROM test_subj ''')

# Destination
for row in curr_msql:
curr_psql.execute(''' INSERT INTO subs (
created, modified,
subjcode,
subjname,
is_pe_or_nstp)

VALUES (current_timestamp,
current_timestamp,
%s, %s,
CASE
WHEN code like '%%PE%%' or code like '%%NSTP%%'

Shouldn't the above be?:

subjcode like '%%PE%%' or subjcode like '%%NSTP%%'

Turns out that won't work as you cannot refer to a column in the CASE:

cur.execute("insert into cell_per(category, cell_per, season,
plant_type, short_category) values('herb test', 1, 'annual', CASE WHEN
category like '%%herb%%' THEN 'herb' ELSE 'flower' END, 'ht' )")

ProgrammingError: column "category" does not exist
LINE 1: ...gory) values('herb test', 1, 'annual', CASE WHEN category l...
^
HINT: There is a column named "category" in table "cell_per", but it
cannot be referenced from this part of the query.

This works:

cur.execute("insert into cell_per(category, cell_per, season,
plant_type, short_category) values(%s, 1, 'annual', CASE WHEN %s like
'%%herb%%' THEN 'herb' ELSE 'flower' END, 'ht' )", ('herb test', 'herb
test'))

So change code to row['code']?

Insufficient caffeine.

...
WHEN %s like '%%PE%%' or %s like '%%NSTP%%'

...
, (row['code'], row['subjectname'], row['code'], row['code'])

FYI this is why I like the named parameters then the above could be
shortened to:

{'code': row['code'], 'subjectname': row['subjectname']}

and you get clearer query code:

VALUES (current_timestamp, current_timestamp,
%(code)s, %(subjectname)s,
CASE
WHEN %(code)s like '%%PE%%' or %(code)s like '%%NSTP%%'

THEN True
ELSE False
END)

THEN True

ELSE False
END) ''', (row['code'], row['subjectname']))

I am getting TypeError: not all arguments converted during string
formatting.

Any advice pls?

--
Adrian Klaver
adrian.klaver@aklaver.com

Using %s works. I also learned that if I just use '%PE%' or '%NSTP%', the
LIKE expression will treat them as placeholder. Solution is to double the
percent signs.

Thanks a lot guys! I love you all.

#8Peter J. Holzer
hjp-pgsql@hjp.at
In reply to: tango ward (#1)
Re: case statement within insert

On 2018-05-25 17:04:25 +0800, tango ward wrote:

I want to insert data from mysql into a table in postgresql. I want to check
when the subjectcode contains PE or NSTP so I can assign True or False to
another column in destination DB.

# Source data:

 # Source data: MySQL
   curr_msql.execute(''' SELECT code, subjectname
                          FROM test_subj ''')

# Destination
for row in curr_msql:
            curr_psql.execute(''' INSERT INTO subs (
                                                    created, modified,
                                                    subjcode, subjname,
                                                    is_pe_or_nstp)

                                  VALUES (current_timestamp, current_timestamp,
                                          %s, %s,
                                          CASE
        WHEN code like '%%PE%%' or code like '%%NSTP%%'
        THEN True
        ELSE False
    END) ''', (row['code'], row['subjectname']))

Others have already explained why that doesn't work and how you can fix
it.

But since you are inserting one row at a time in a Python loop, I don't
see any advantage in writing the condition in SQL. Do it in Python
instead:

for row in curr_msql:
is_pe_or_nstp = 'PE' in row['code'] or 'NSTP' in row['code']
curr_psql.execute(''' INSERT INTO subs (
created, modified,
subjcode, subjname,
is_pe_or_nstp)

VALUES (current_timestamp, current_timestamp,
%s, %s,
%s)
''',
(row['code'], row['subjectname'],
is_pe_or_nstp,))

A bit more readable, IMHO.

Alternatively, import the complete table *unchanged* from MySQL (you can
use copy_from() for this which is much faster than individual inserts),
and then convert it with a single SQL statement.

hp

--
_ | Peter J. Holzer | we build much bigger, better disasters now
|_|_) | | because we have much more sophisticated
| | | hjp@hjp.at | management tools.
__/ | http://www.hjp.at/ | -- Ross Anderson <https://www.edge.org/&gt;