使用INSERT ... OUTPUT与pyodbc时如何获取IDENTITY值

时间:2017-11-08 20:24:05

标签: python sql-server pyodbc

我正在尝试使用OUTPUT获取新插入行的ID。但是,我遇到了HY010错误。我使用的是以下查询/代码:

string = """
         SET NOCOUNT ON;
         DECLARE @NEWID TABLE(ID INT);

         INSERT INTO dbo.t1 (Username, Age)
         OUTPUT inserted.id INTO @NEWID(ID)
         VALUES(?, ?)

         SELECT ID FROM @NEWID
         """

cursor.execute(string, "John Doe", 35)
cursor.commit()
id = cursor.fetchone()[0]

最后一行id = cursor.fetchone()[0]导致HY010错误(见下文)。任何建议将不胜感激!

pyodbc.Error: ('HY010', '[HY010] [Microsoft][ODBC SQL Server Driver]Function sequence error (0) (SQLFetch)')

3 个答案:

答案 0 :(得分:4)

我能够重现您的问题,我能够通过在INSERT之后立即检索id值并在提交之前检索来避免它。也就是说,而不是

cursor.execute(string, "John Doe", 35)
cursor.commit()
id = cursor.fetchone()[0]

我做了

cursor.execute(string, "John Doe", 35)
id = cursor.fetchone()[0]  # although cursor.fetchval() would be preferred
cursor.commit()

答案 1 :(得分:2)

如果您将SQLAlchemy与engine一起使用,则可以在运行查询和获取表ID之前检索这样的PyODBC游标。

    connection = sql_alchemy_engine.raw_connection()
    cursor = connection.cursor()
    result = cursor.execute(
        """
        INSERT INTO MySchema.MyTable (Col1, Col2) OUTPUT INSERTED.MyTableId 
        VALUES (?, ?);
        """,
        col1_value,
        col2_value,
    )
    myTableId = cursor.fetchone()[0]
    cursor.commit()
    print("my ID is:", myTableId)

答案 2 :(得分:1)

对我来说,这仅适用于Azure SQL Serverless(使用 pyodbc == 4.0.28 ):

//REACT
import React, {useContext, useEffect, useState} from 'react';
//MUI COMPONENTS
import {
    Grid,
    IconButton,
    Paper,
    Table,
    TableBody,
    TableCell,
    TableContainer,
    TableHead,
    TableRow,
    TextField,
    Typography,
    useMediaQuery,
    useTheme,
} from '@material-ui/core';
//MUI ICONS
import {Close as CloseIcon, Done as DoneIcon, Edit as EditIcon, Refresh as RefreshIcon} from '@material-ui/icons';
//CONTEXTS
import {NewTagContext} from '../../providers/NewTagContext';
//CUSTOM COMPONENTS
import CreateFields from '../components/CreateFields';
import DeleteButton from '../components/DeleteButton';
//CONFIG FILES
import textFields from './config/textFields.json';
import constraints from './config/textFields.constraints.json';

const TagTable = () => {
          //HOOKS START
          const context = useContext(NewTagContext);
          const {tags} = context;
          const theme = useTheme();
          const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
          //HOOKS END

          //STATE START
          useEffect(() => {
              if (!context.tags) context.read();
          }, [context]);

          const initialState = {tagEditId: null, tag: null};
          const [state, setState] = useState(initialState);
          //STATE END

          //FUNCTIONS START
          const setEdit = (tag) => {
              setState({
                  tagEditId: tag.id ? tag.id : null,
                  tag:       {...tag},
              });
          };

          const onEditSubmit = (e) => {
              e.preventDefault();
              context.update(state.tag);
              setState(initialState);
          };

          const onEditClose = () => {
              context.resetTag(state.tag);
              setState(initialState);
          };
          //FUNCTIONS END

          return (
              <TableContainer component={Paper}>
                  <Table size="small">
                      <TableHead>
                          <TableRow>
                              <TableCell colSpan={2}>
                                  <Grid container justify="flex-end" alignItems="center">
                                      <Grid item xs={isMobile}>
                                          <CreateFields entityName="tag" textFields={textFields} constraints={constraints}
                                                        createFunction={context.create}/>
                                      </Grid>
                                      <Grid item>
                                          <IconButton onClick={context.read}><RefreshIcon/></IconButton>
                                      </Grid>
                                  </Grid>
                              </TableCell>
                          </TableRow>
                          <TableRow>
                              <TableCell>Tag Name</TableCell>
                              <TableCell align="right">Actions</TableCell>
                          </TableRow>
                      </TableHead>
                      <TableBody>
                          {tags && tags.map((tag, index) => (
                              <TableRow key={tag.id}>
                                  <TableCell>
                                      {state.tagEditId === tag.id ?
                                          <form noValidate onSubmit={onEditSubmit}>
                                              <TextField type="text" value={tag.name} label={state.tag.name} name="name"
                                                         fullWidth
                                                         autoFocus onFocus={(e) => e.target.select()}
                                                         onChange={(e) => context.handleChange(index, e)}/>
                                          </form>
                                          :
                                          <Typography>{tag.name}</Typography>
                                      }
                                  </TableCell>
                                  <TableCell align="right">
                                      {state.tagEditId !== tag.id ?
                                          <>
                                              <IconButton color="inherit" onClick={() => setEdit(tag)}>
                                                  <EditIcon/>
                                              </IconButton>
                                              <DeleteButton deleteFunction={context.delete} entity={tag}/>
                                          </>
                                          :
                                          <>
                                              <IconButton color="primary" onClick={onEditSubmit}>
                                                  <DoneIcon/>
                                              </IconButton>
                                              <IconButton color="secondary" onClick={onEditClose}>
                                                  <CloseIcon/>
                                              </IconButton>
                                          </>
                                      }
                                  </TableCell>
                              </TableRow>
                          ))
                          }
                      </TableBody>
                  </Table>
              </TableContainer>
          );
      }
;

export default TagTable;