查找数据表中不存在的ID号

CREATE PROCEDURE sp_recycle
AS
DECLARE @maxid int,@sql varchar(8000)
IF exists(SELECT * FROM t)
BEGIN
  SELECT @maxid=MAX(id) FROM t
  CREATE TABLE #t(id int)
  SET @sql='SELECT TOP '+CAST(@maxid AS varchar)+' IDENTITY(int,1,1) id
              INTO #tem FROM syscolumns a,syscolumns b,syscolumns c
            INSERT #t
              SELECT * FROM #tem
            DROP TABLE #tem '
  EXEC(@sql)
  SELECT id FROM #t WHERE not exists(SELECT * FROM t WHERE id=#t.id)
  DROP TABLE #t
END
GO
<think> 根据用户的问题,用户想要在数据流中查找GGA数据的方法。 根据引用[1]和[2]的内容,我们知道NMEA数据流是由多条同格式的报文组成的,每条报文以逗分隔,且以独立行存在(通常以回车换行结束)。最常用的格式是GGA,它包含定位时间、纬度、经度、高度等信息。 方法: 1. NMEA数据流通常是一行一行的文本数据,每一行代表一条完整的NMEA语句。 2. 每条NMEA语句以“$”开头,接着是5个字母的标识符,其中前两个字母表示设备类型(如GP表示GPS),后三个字母表示语句类型(如GGA)。 3. 因此,查找GGA数据就是查找以“$GPGGA”或“$xxGGA”(xx可能为其他设备类型,如GL、GN等)开头的行。 具体步骤: 假设我们有一个数据流(可能是串口实时读取的数据,或者是已经记录下来的文本文件),我们可以逐行读取,然后判断该行是否以GGA标识开头。 示例代码(Python): 由于引用[2]提到可以通过字节匹配简单处理,我们可以使用字符串匹配的方法。 注意:NMEA语句以回车换行结束(通常是\r\n),但在同系统可能同,所以读取时按行读取即可。 代码: 这里我们假设数据流来自串口或文本文件,我们按行读取并检查每行是否以“$GPGGA”开头(或者更通用一点,检查是否包含“GGA”作为语句标识,但要注意位置,因为NMEA语句标识在开头第3到第5个字符?实际上,标识符是从第1个字符开始,格式为:$aaaab,其中aaaa是设备类型和语句类型,通常设备类型两个字符,语句类型三个字符。所以GGA是语句类型的三个字符,它出现在第三个字段?对,应该是:$XXGGA,其中XX是两个字符的设备类型,如GP。所以完整的GGA语句开头是“$xxGGA”,其中xx可以是GP、GL、GN等。 因此,我们可以检查每行是否以“$”开头,并且接下来的5个字符中,后三个是“GGA”。但更简单的方法是检查行是否以“$”开头并且包含“GGA”作为语句类型标识。注意:语句类型标识在开头后第3到第5个字符(即索引3到5,如果从1开始计数)?实际上,字符串索引从0开始: 第0位:'$' 第1位:第一个设备类型字符 第2位:第二个设备类型字符 第3-5位:三个字符的语句类型(即第3,4,5位) 所以,我们可以检查第3到第5位(即索引3,4,5)是否为"GGA"。但是,注意有些语句可能是以设备类型开头?根据标准,设备类型是两个字符,所以语句标识总共5个字符(设备类型2+语句类型3)。因此,我们可以检查字符串的前6个字符(包括'$')中,从索引3到5的子串是否为"GGA"。 另一种简单方法:检查该行是否以“$xxGGA”的形式开头,其中xx是两个任意字符。但是,我们也可以直接查找“GGA”作为语句标识,但要注意避免误匹配(比如数据部分出现GGA)。根据NMEA标准,逗之前的部分是语句头,第一个逗之前就是语句标识(包括$和5个字符的标识符)。所以我们可以先提取第一个逗之前的部分,然后判断它是否以“$”开头且以“GGA”结尾(总长度为6,即5个字符的标识符加上$)。 但为了简单,我们通常只需要检查开头的6个字符中是否包含“GGA”,因为GGA是语句类型,它出现在第4,5,6个字符(索引3,4,5)的位置。例如: $GPGGA,... 012345 索引0是'$',1是'G',2是'P',3是'G',4是'G',5是'A'。所以索引3,4,5正好是"GGA"。 所以我们可以这样判断:如果一行的长度大于5,并且从索引3到5的字符是"GGA",那么这就是GGA语句。 但是,还有一种情况是语句标识可能是以GP开头,比如可能是GLONASS的$GLGGA,或者北斗的$BDGGA,或者多系统的$GNGGA。所以通用方法是检查第3到第5个字符(索引3,4,5)是否为"GGA"。 代码示例: 假设我们有一行数据:line = "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47" 步骤: 1. 检查字符串是否以'$'开头 2. 检查长度是否足够(至少6个字符) 3. 检查索引3到5(即第4,5,6个字符)是否为"GGA" 注意:索引从0开始,所以索引3是第4个字符(即第3个位置),索引5是第6个字符(即第5位置)。所以切片是line[3:6](在Python中,切片是左闭右开,所以[3:6]取索引3,4,5)。 因此,判断条件:if line.startswith('$') and len(line)>=6 and line[3:6]=='GGA' 这个方法可以匹配任何设备类型的GGA语句。 另外,还有一种更严格的方式:先判断前6个字符是否符合NMEA语句头的格式,然后取后三个字符判断。但上述方法已经足够。 代码实现: 实时数据流(例如串口)中读取并提取GGA: 使用pyserial读取串口的例子: ```python import serial ser = serial.Serial('/dev/ttyUSB0', 9600) # 根据实际情况修改串口和波特率 while True: line = ser.readline().decode('ascii', errors='ignore').strip() # 检查是否是GGA语句 if line.startswith('$') and len(line) >= 6 and line[3:6] == 'GGA': # 处理GGA语句 print("GGA data:", line) # 这里可以解析GGA语句 ``` 如果是文本文件: ```python with open('gps_data.txt', 'r') as f: for line in f: line = line.strip() if line.startswith('$') and len(line) >= 6 and line[3:6] == 'GGA': print("Found GGA:", line) ``` 解析GGA语句: 根据引用[1],GGA语句的格式如下(以逗分隔): $GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>,<13>,<14>*hh<CR><LF> 字段说明: 1: UTC时间,格式为hhmmss.ss(时分秒.毫秒) 2: 纬度,格式为ddmm.mmmm(度分格式) 3: 纬度方向,N或S 4: 经度,格式为dddmm.mmmm 5: 经度方向,E或W 6: 定位质量指示器(0=无效,1=GPS定位,2=差分GPS定位等) 7: 使用的卫星数量(00-12) 8: 水平精度因子(HDOP) 9: 海拔高度,单位米 10: 地球椭球面相对大地水准面的高度(单位米) 11: 差分时间(从最近一次接收到差分信开始的秒数,非差分定位为空) 12: 差分站ID(0000-1023,非差分定位为空) 13: 校验和(以*开头,两位十六进制数) 注意:实际字段可能有细微差别,但大致如此。最后一个字段是校验和,我们可能需要自己校验,因为有些解析库会校验,但如果我们自己解析,可以忽略校验和或者进行校验。 解析示例(将GGA字符串解析为各个字段): 使用split(',')分割字符串,然后按顺序提取字段。 示例代码(解析GGA字符串): ```python def parse_gga(gga_line): # 去掉换行符等 gga_line = gga_line.strip() # 检查校验和(可选) # 先分割 parts = gga_line.split(',') if len(parts) < 15: return None # 字段够 # 提取字段 try: utc_time = parts[1] latitude = parts[2] lat_direction = parts[3] longitude = parts[4] lon_direction = parts[5] quality = int(parts[6]) num_satellites = int(parts[7]) hdop = float(parts[8]) altitude = float(parts[9]) # 后面的字段可能为空,所以注意处理 # ... 其他字段根据需求提取 except (ValueError, IndexError) as e: print(f"解析错误: {e}") return None # 将纬度从ddmm.mmmm格式转换为十进制度 # 例如:4807.038 -> 48度07.038分 -> 48 + 7.038/60 = 48.1173度 lat_deg = float(latitude[:2]) lat_min = float(latitude[2:]) lat_decimal = lat_deg + lat_min / 60.0 if lat_direction == 'S': lat_decimal = -lat_decimal # 经度类似,注意经度是dddmm.mmmm(三位度) lon_deg = float(longitude[:3]) lon_min = float(longitude[3:]) lon_decimal = lon_deg + lon_min / 60.0 if lon_direction == 'W': lon_decimal = -lon_decimal result = { 'utc_time': utc_time, 'latitude': lat_decimal, 'longitude': lon_decimal, 'quality': quality, 'num_satellites': num_satellites, 'hdop': hdop, 'altitude': altitude } return result ``` 使用示例: 在找到GGA行后,调用parse_gga函数解析。 注意:上面的转换是简单的,实际应用中可能需要更健壮的解析,并注意异常处理。另外,如果数据流中可能包含其他字符(如换行符等),需要确保字符串完整。 总结: 在数据流中查找GGA数据的方法就是逐行扫描,并判断每行是否以“$”开头且第4到第6个字符(索引3:6)为“GGA”。 根据引用[2],用户也可以选择解析RMC语句,但这里用户明确要求GGA。 因此,回答用户的问题:可以通过逐行扫描数据流,并匹配行开头的特定标识($xxGGA)来查找GGA数据。 </think> 在数据流中查找GGA数据的方法如下,主要基于NMEA协议的格式特征和数据处理技巧: ### 查找GGA数据的方法 1. **识别数据流特征** - GGA语句以`$xxGGA`开头(xx为设备类型,如GP/GL/BD) - 完整格式示例:`$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47` - 每条语句以换行符结束(通常为`\r\n`或`\n`) 2. **核心查找逻辑** ```python def find_gga(data_stream): gga_lines = [] # 按换行符分割数据流 lines = data_stream.split('\n') for line in lines: # 清理空白字符并检查语句头 line = line.strip() if line.startswith('$') and line[3:6] == 'GGA': gga_lines.append(line) return gga_lines ``` 3. **实时串口处理方法(Python示例)** ```python import serial ser = serial.Serial('/dev/ttyUSB0', 9600) # 配置串口参数 buffer = "" while True: # 读取串口数据并解码 data = ser.read(ser.in_waiting).decode('ascii', errors='ignore') buffer += data # 按换行符分割处理 if '\n' in buffer: lines = buffer.split('\n') # 保留未完成的行 buffer = lines.pop() for line in lines: line = line.strip() if line.startswith('$') and 'GGA' in line[1:6]: print("Found GGA:", line) # 在此添加解析处理代码 ``` 4. **关键技巧** - **缓存管理**:使用缓冲区处理完整数据包 - **快速验证**:检查前6字符包含`$`和`GGA`(位置3-5) - **错误处理**:添加CRC校验(如`*47`部分)验证数据完整性 - **性能优化**:避免正则表达式,用基础字符串操作提升效率 ### 解析GGA数据示例 ```python def parse_gga(gga_line): fields = gga_line.split(',') return { 'time': fields[1], # UTC时间 (hhmmss.ss) 'latitude': f"{fields[2]}{fields[3]}", # 纬度+方向 'longitude': f"{fields[4]}{fields[5]}", # 经度+方向 'quality': int(fields[6]), # 定位质量 (0-2) 'satellites': int(fields[7]), # 卫星数量 'altitude': f"{fields[9]}{fields[10]}" # 海拔+单位 } ``` ### 注意事项 1. 多设备兼容性:支持`$GPGGA`(GPS), `$GLGGA`(GLONASS), `$BDGGA`(北斗)等 2. 异常处理:添加超时机制(如30秒无数据重置缓冲区) 3. 数据验证:通过`*`后的校验和验证数据完整性 4. 效率优化:对于高频率数据(如10Hz),建议使用状态机代替字符串分割 > 在实际应用中,GGA报文更新频率通常为1Hz,包含关键定位信息如经纬度、海拔和时间戳,是GPS数据解析中最常用的报文类型[^1]。对于需要完整NMEA库的简单应用,直接字节匹配是最高效的解决方案[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值