1

所以我正在使用 Java 在 SQL 中创建一个数据库,但我一直遇到一个我无法解决的问题。非常感谢一些帮助。我正在使用以下代码将数据读入数据库。我目前将数据库命名为 newTestTable2,它有 4 列:stockID (INT)、millisFromMid (INT)、bidPrice (DOUBLE) 和 askPrice (DOUBLE)。我正在尝试使用准备好的语句向数据库添加新信息,使用 stockID 作为主键,但我遇到了很多麻烦。这是代码:

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.util.zip.GZIPInputStream;


public class ReadGZippedTAQQuotesFile {

    // Header fields

    protected int _secsFromEpoch;
    protected int _nRecs;

    // Record fields

    protected int   [] _millisecondsFromMidnight;
    protected int   [] _bidSize;
    protected float [] _bidPrice;
    protected int   [] _askSize;
    protected float [] _askPrice;

    public int getSecsFromEpoch () { return _secsFromEpoch; }
    public int getNRecs         () { return _nRecs;         }

    public int   getMillisecondsFromMidnight ( int index ) { return _millisecondsFromMidnight[ index ]; }
public int   getBidSize                  ( int index ) { return _bidSize[ index ];                  }
public float getBidPrice                 ( int index ) { return _bidPrice[ index ];                 }
public int   getAskSize                  ( int index ) { return _askSize[ index ];                  }
public float getAskPrice                 ( int index ) { return _askPrice[ index ];                 }

public static Connection connect = null;
public static PreparedStatement pst = null;
public static PreparedStatement pst1 = null;
public static PreparedStatement pst2 = null;
public static PreparedStatement pst3 = null;
public static ResultSet resultSet = null;

/**
 * Constructor - Opens a gzipped TAQ quotes file and reads entire contents into memory.
 * 
 * @param filePathName Name of gzipped TAQ quotes file to read
 * @throws IOException 
 */
public ReadGZippedTAQQuotesFile( File filePathName ) throws IOException {

    // Open file 

        InputStream in = new GZIPInputStream( new FileInputStream( filePathName ) );
        DataInputStream dataInputStream = new DataInputStream( in );

    // Read and save header info

        _secsFromEpoch = dataInputStream.readInt();
        _nRecs = dataInputStream.readInt();

    // Allocate space for data

        _millisecondsFromMidnight = new int   [ _nRecs ];
        _bidSize                  = new int   [ _nRecs ];
        _bidPrice                 = new float [ _nRecs ];
        _askSize                  = new int   [ _nRecs ];
        _askPrice                 = new float [ _nRecs ];

    // Read all records into memory

        for( int i = 0; i < _nRecs; i++ )
            _millisecondsFromMidnight[ i ] = dataInputStream.readInt();

        for( int i = 0; i < _nRecs; i++ )
            _bidSize[ i ] = dataInputStream.readInt();

        for( int i = 0; i < _nRecs; i++ )
            _bidPrice[ i ] = dataInputStream.readFloat();

        for( int i = 0; i < _nRecs; i++ )
            _askSize[ i ] = dataInputStream.readInt();

        for( int i = 0; i < _nRecs; i++ )
            _askPrice[ i ] = dataInputStream.readFloat();

    // Finished reading - close the stream

        dataInputStream.close();

}

/**
 * Example of using this class to read a TAQ quotes file and access
 * individual records.
 * @throws ClassNotFoundException 
 * @throws SQLException 
 */
public static void quotesReader() throws ClassNotFoundException, SQLException {
    File f = new File("/Users/Adam/Desktop/SQL Folder/20070620/20070620");
    File[] files = f.listFiles();

    try {

        // This will load the MySQL driver
        Class.forName("com.mysql.jdbc.Driver");

        // Setup the connection with the DB
        connect = DriverManager.getConnection( 
                "jdbc:mysql://localhost:3306/newTest", "root", "Kariya"
                );

        // Statements allow us to issue SQL queries to the database
        pst = connect.prepareStatement("INSERT INTO newTestTable2(stockID) VALUES(?)");
        pst1 = connect.prepareStatement("INSERT INTO newTestTable2(millisFromMid) VALUES(?)");
        pst2 = connect.prepareStatement("INSERT INTO newTestTable2(bidPrice) VALUES(?)");
        pst3 = connect.prepareStatement("INSERT INTO newTestTable2(askPrice) VALUES(?)");

        // Read entire TAQ quotes file into memory

        pst.setInt(1, 0);
        pst.executeUpdate();

        for( int i=0; i < files.length; i++) {
            ReadGZippedTAQQuotesFile taqQuotes = new ReadGZippedTAQQuotesFile( files[i] );

            pst.setInt(1, i+1);
            pst.executeUpdate();

            // Iterate over all records, writing the contents of each to the console

            int nRecs = taqQuotes.getNRecs();
            for( int j = 0; j < nRecs; j++ ) {

                pst1.setInt(1, taqQuotes.getMillisecondsFromMidnight( j ));
                pst1.executeUpdate();
                pst2.setDouble(1, taqQuotes.getBidPrice( j ));
                pst2.executeUpdate();
                pst3.setDouble(1, taqQuotes.getAskPrice( j ));
                pst3.executeUpdate();

                /*

                System.out.println(
                        taqQuotes.getMillisecondsFromMidnight( j )
                        + ","
                        + taqQuotes.getBidSize( j )
                        + ","
                        + taqQuotes.getBidPrice( j )
                        + ","
                        + taqQuotes.getAskSize( j )
                        + ","
                        + taqQuotes.getAskPrice( j )
                        );

                */
            }
        }
    } catch (IOException e1) {
        e1.printStackTrace();
    } finally {
        try {
            if (pst != null) {
                pst.close();
            }
            if (pst1 != null) {
                pst1.close();
            }

            if (pst2 != null) {
                pst2.close();
            }

            if (pst3 != null) {
                pst3.close();
            }

            if (connect != null) {
                connect.close();
            }
        } catch (Exception e) {

        }
    }
}

public static void main( String[] args ) throws ClassNotFoundException, SQLException {
    quotesReader();
}

}

我得到以下异常

 Exception in thread "main"
  com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:
  Duplicate entry '0' for key 'PRIMARY'"

所以我知道它告诉我我使用同一个股票 ID 的次数太多了,但是如果我不使用以下行:

pst.setInt(1, 0);
pst.executeUpdate();

然后它返回stockID没有默认值,这看起来也很奇怪,因为 INT 应该有一个默认值 0 对吗?看起来这段代码应该在正确的附近,但我看不出是什么导致了这个错误。任何人都可以分享一些见解吗?

4

3 回答 3

1

你真的需要4个准备好的陈述吗?您是否需要为每个 taqQuotes 插入 1 行数据?如果是这样,那么我会这样做:

public static void quotesReader() throws ClassNotFoundException, SQLException {
  File f = new File("/Users/Adam/Desktop/SQL Folder/20070620/20070620");
  File[] files = f.listFiles();

  try {
    Class.forName("com.mysql.jdbc.Driver");
    connect = DriverManager.getConnection( 
            "jdbc:mysql://localhost:3306/newTest", "root", "Kariya"
            );
    long counter = 1; // place this before the for(int i=0...) loop
    pst = connect.prepareStatement("INSERT INTO newTestTable2(stockID, millisFromMid, bidPrice, askPrice) VALUES(?,?,?,?)");

    for( int i=0; i < files.length; i++) {
      ReadGZippedTAQQuotesFile taqQuotes = new ReadGZippedTAQQuotesFile( files[i] );
      int nRecs = taqQuotes.getNRecs();
      for( int j = 0; j < nRecs; j++ ) {
        pst.setInt(1, counter++);
        pst.setInt(2, taqQuotes.getMillisecondsFromMidnight( j ));
        pst.setDouble(3, taqQuotes.getBidPrice( j ));
        pst.setDouble(4, taqQuotes.getAskPrice( j ));
        pst.executeUpdate();
      }
    }
  } catch (IOException e1) {
    e1.printStackTrace();
  } finally {
    try {
        if (pst != null) {
            pst.close();
        }
        if (connect != null) {
            connect.close();
        }
    } catch (Exception e) {

    }
  }
}

这将为每个 taqQuotes 插入 1 条记录,而不是 4 条记录,每条记录仅填充一列

于 2012-12-27T03:09:56.383 回答
0

你好朋友你需要改变你的代码。

在您正在执行的第一个 for 循环中pst.executeUpdate(),其中包含查询"INSERT INTO newTestTable2(stockID) VALUES(?)"。在内部循环中,您也在执行不包含主键的准备好的语句。由于股票 id 不是自动递增字段,您需要在插入记录时显式传递它.顺便说一下,你不需要两个循环来完成这项任务。

于 2012-12-27T03:13:23.080 回答
0

这里的问题是我想使用 stockID 作为主键,同时使用 stockID 来识别每只股票。这行不通,因为我每只股票有数百行数据,所以我需要 stockID 才能重复。正如上面的每个人都指出的那样,主键应该是唯一的。我尝试了 JScoobyCed 建议的方向,它确实有助于清理代码,但仍然存在唯一性问题。所以我找到的解决方案是不要将 stockID 作为主键,而是将行计数器作为主键。

顺便说一句,我的代码可能不是解决这类问题的最佳方法,因为它非常慢,但它确实有效。学习更快的方法将大量数据输入 SQL 会很有趣。

于 2012-12-27T18:54:39.707 回答